継承元の関数はオーバーロードできないのですか?

このQ&Aのポイント
  • 継承元の関数はオーバーロードできないのでしょうか?コンパイルエラーが出る
  • 参考書にはそのような事例が書かれていないので、どなたか教えていただけないでしょうか
  • 継承元の関数の呼び出しでコンパイルエラーが発生する。オーバーロードはできない?
回答を見る
  • ベストアンサー

継承元の関数はオーバーロードできないのですか?

#include <stdlib.h> /* 動物クラス */ class CAnimal{ public: int type; void init(int); void prt(void); }; /* 犬クラス */ class CDog : public CAnimal{ public: void init(void); }; /*------------ 動物クラス ------------*/ void CAnimal::init(int t){ type = t; } void CAnimal::prt(void){ printf("%d\n", type); } /*------------ 犬クラス ------------*/ void CDog::init(void){ type = 10; } /*------------ メイン関数 ------------*/ void main(void) { CDog dog; dog.init(1); dog.prt(); } メイン関数の「dog.init(1)」(下から3行目)でコンパイルエラーが出ます。継承元の関数はオーバーロードできないのでしょうか? 参考書にはそんなこと書いてありませんし、検索しても似たような事例が見つかりません。 初歩的なことですみませんが、どなたか教えていただけないでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • Werner
  • ベストアンサー率53% (395/735)
回答No.2

class CDog : public CAnimal{ public: using CAnimal::init; //追加 void init(void); }; としてみてください。 Effective C++ の50項によると継承元の関数を意図せず呼び出すことがないようにこのような仕様になっているらしい。 # 参考URLは検索して見つけた。 # Effective C++に書いてあるって言うから実際に見てみると確かにこの話題だった。

参考URL:
http://ml.tietew.jp/cppll/cppll/article/6092
jeddom
質問者

お礼

ご回答ありがとうございます。 なるほど、コンパイラの親切だったんですね。 usingを追加したらコンパイルできました。ありがとうございます。

その他の回答 (2)

  • hidebun
  • ベストアンサー率50% (92/181)
回答No.3

#1です。よくオーバーライドの説明で見るサンプルでしたので(動物とか犬とか)、勘違いしました。 よく読まずで申し訳ありませんでした。 オーバーロードについて、勉強になりました。 個人的には、ややこしそうなので、あんまり使わないかな…^^;

jeddom
質問者

お礼

いえいえ^^ わざわざありがとうございます

  • hidebun
  • ベストアンサー率50% (92/181)
回答No.1

仮想関数、virtual、を調べてみて下さい。 例としては以下。 http://d.hatena.ne.jp/unageanu/20070916/1189933146

jeddom
質問者

お礼

さっそくのご回答ありがとうございます。 上のURLを見たのですが、オーバーライドについて書かれていて、オーバーロードについては書かれていないような気がするのですが・・・。

関連するQ&A

  • オーバーロードしたメンバ関数が継承後,利用できない

    オーバーロードしたメンバ関数のクラスを継承後,そのメンバ関数と同名のメンバ関数を定義すると,オーバーロードしたメンバ関数が呼び出せなくなります.何故でしょうか? 質問を一言で正確に表現できてないと思いますので,状況を順を追って説明します. まず,クラスT1にメンバ関数m(int)があったとします. そのメンバ関数をオーバーロードしてm(float)を作ったとします. そして,T1を継承してT2を定義し,その中でメンバ関数m(int)をオーバーライドすると,T2のオブジェクトではm(float)が呼び出せなくなってしまいました. 何故この様なことをするかといいますと,m(string)はstringの引数をある関数で変換して整数にしてから,intでm(int)を呼び出しているとします. T2でも,stringによってm(int)を呼び出すので,T1で定義したm(string)をT2でもそのまま使いたいのです. 例です class T1{ public: virtual void m(int i){cout<<i<<"T1\n";} void m(string s){m((int)s[0]);} }; class T2{ public: virtual void m(int i){cout<<i<<"T2\n";} }; int main(){ T2 t; string s("a"); // t.m(s); /*error*/ t.T1::m(s); } 出力 97T2 T1のm(string)はT2のm(int)を呼び出してます. 何か解決策ありますでしょうか? また,言語の仕様がこの様になってるのは,この様なことをすると問題があるからだと思うのですが,どのような問題が起こるので禁止されてるのでしょう? それとも実は,この様なことはできるのでしょうか? (つまり,単に私のプログラムが間違ってる)

  • ->*演算子のオーバーロードについて

    こんにちは。質問させてください。 現在下記のような処理(main関数でやっているような処理)を実現させたいのですが、うまくコンパイルできません。 #include <iostream> class Test { public:   void TestFunc()   {     std::cout << "TestFunc" << std::endl;   } }; class AllowOverLoad { public:   Test* operator ->()   {     return new Test;   } }; int main() {   void ( Test::*lpTestFunc )() = &Test::TestFunc;   AllowOverLoad overload;   ( overload->*lpTestFunc )(); } 主なエラーは error C2296: '->*' : 無効です。左オペランドには型 'AllowOverLoad' が指定されています。 です。 おそらくこの問題を解決するにはAllowOverLoadに->*演算子をオーバーロードしなくてはいけないと思うのですが、->*演算子のオーバーロード方法がいまいちよくわかりません。 いい文献やHPも見つけられなかったので質問させていただきました。 /* 現在、本番のコーディングでは暗黙的なキャストを禁止しているのでAllowOverLoadクラスに暗黙的にTest*型にキャストするような処理はなしの方向で、あくまで->*演算子のオーバーロードということでお願いします。 Microsoft WindowsXP Professional Edition VisualStudio 2008 AcademicEdition */ よろしくお願いします。

  • new演算子のオーバーロードについて

    #include <stdio.h> #include <windows.h> class MyNew { public: void* ptr; MyNew( void* p ) { ptr = p; } void* MyNew::operator new( size_t size ) { printf("new-\n"); return malloc( size ); } void MyNew::operator delete( void* ptr ) { printf("delete-\n"); free( ptr ); } }; void main( void ) { MyNew p = new int; } クラスのメモリ確保をnew演算子のオーバーロードを用いて書いてみたのですがオーバーロードしたnew演算子が呼ばれません。 なぜでしょうか? /** VisualStdio2005コンソールアプリケーション WindowsXP */

  • メンバ関数ポインタを値とするコンテナの定義方法

    こんにちは、boundaryといいます。 あるクラスのメンバ関数のポインタをmapで管理したいので すが、定義でエラーになってしまいます。 class CFunc { private: bool FuncA(); bool FuncB(); }; このようなクラスに対して、 template <class T> class FuncMap { private: typedef bool (T::*Func)(); typedef map<int, T::Func> _FuncMap; _FuncMap FMap; public: void set(int, T::Func); T::Func search(int); }; を用意しました。 template <class T> void FuncMap<T>::set(int i, T::Func pFunc) { FMap.insert(pair<int , T::Func>(i ,pFunc)); } template <class T> T::Func FuncMap<T>::search(int i) { map<T::Func, int>::iterator FuncMapIte; FuncMapIte = FMap.find(i); return T::Func; } と書いたのですが、 error C2244: 'FuncMap<T>::set' : 関数のオーバーロードが解決できません。 error C2954: テンプレートの定義はネストできません。 error C2244: 'FuncMap<T>::search' : 関数のオーバーロードが解決できません。 との事です。 色々試行錯誤したのですが、うまくいきません。 定義のどこがいけないのでしょうか? よろしくお願いします。 VC6.0SP5 WINDOWS2000です。

  • 仮想関数と継承について

    #include <iostream> using namespace std; class AAA { public: virtual aaa() { cout <<"aaa(void)"<<endl;} }; class BBB : public AAA { public: virtual aaa(int a) { cout <<"aaa(int)"<<a<<endl;} }; int main() { BBB bbb; bbb.aaa();<--これがエラーになります。 return 0; } どうして、既定クラスの引数なしのaaa()はよぶことが できないのでしょうか?

  • ラムダ式を関数に渡したいのですが

    Class1からClass2にある関数の引数にラムダ式で関数を渡すようなプログラムを作ろうと思い、以下のようにコードを記述しました。 #include <iostream> class Class1 { int i = 0; void func() { std::cout << "Hello world" << std::endl; } void init() { Class2 *class2 = new Class2(); class2->setFunc([this] { func(); i++; }()); } }; class Class2 { void(*mFunc)(); void runFunc(){ mFunc(); } public: void setFunc(void func()) { mFunc = func; } }; すると class2->setFunc([this] { func(); i++; }()); のところで「型"void"の引数は型"void(*)()"のパラメーターと互換性がありません」というエラーが発生してしまいます。 キャプチャにthisを渡したラムダ式を他のクラスの関数ポインタのような変数に代入させるようにしたいのですがどのように記述したらできますか

  • 継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか?

    継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか? 以下のようなケースで、 #include "stdio.h" using namespace std; // baseクラス class base { private:  int m_nII;  int m_nJJ;  int m_nKK; public:  base(int i,int j,int k){ m_nII=i; m_nJJ=j; m_nKK=k; }  int GetSum(){ return (m_nII+m_nJJ+m_nKK); } }; // base 継承クラス class hoge : public base { public:  hoge() : base(1,2,3){} }; void func(base* obj){ // baseクラスを引数に取る関数  printf("sum is %d\n", obj->GetSum()); } // main int main(){  hoge objHoge;  func((base*)&objHoge); // <-キャストして渡す  return 0; } として、一応、gccでコンパイルは通り、実行結果も期待通りだったのですが、 このやり方で問題は無いのでしょうか? (たとえば継承先のクラスが独自のメンバを持っていたりなどした場合、期待した結果にならないとか・・) よろしくお願いします。

  • c++のvirtual関数および継承について

    以下のプログラムで間違っている部分が分かる方、ご指摘お願い致します。 私の稚拙な腕では、どこが間違っているのかさっぱり分かりません。 以下のプログラムは、クラスticketを継承して、airplaneTicket、cinemaTicketを作成し、チケットの情報を入力し、最後に出力するものです。コンパイルエラーの箇所はコメントアウトしておきました。メイン関数の中に計5箇所あります。 よろしくお願い致します。 #include<string> #include<iostream> #include<vector> using namespace std; class ticket{ public: string ID; string seat; int price; ticket(){ cout << "ticket default constructor" << endl; ID="not Known"; seat="not Known"; } ticket(string i, string t){ cout << "ticket parameter-constructor" << endl; ID=i; seat=t; } virtual void setPrice(int p)=0; void printInfo(){ cout << ID << " " << seat << endl; } }; class airplaneTicket: public ticket{ public: string flight; airplaneTicket(){ cout << "airplane default constructor" << endl; flight="not known yet"; } airplaneTicket(string i, string t, string f):ticket(i, t){ cout << "airplane parameter-constructor" << endl; flight=f; } virtual void setPrice(int p){ string type; cout << "enter class type: "; cin >> type; if(type=="business") price=p*2; else price=p; } void priceInfo(){ cout << ID << " " << seat << " " << price << " " << flight << endl; } }; class cinemaTicket: public ticket{ public: cinemaTicket(){ cout << "cinema default constructor" << endl; } cinemaTicket(string i, string t):ticket(i, t){ cout << "cinema parameter-constructor" << endl; } }; int main(){ ticket tList[100]; //error: invalid abstract type 'ticket' for 'tList' tList[0]=new airplaneTicket("239", "d34", "f345"); //error: no match for 'operator=' in 'tList[0] tList[1]=new airplaneTicket(); // error: no match for 'operator=' in 'tList[1] tList[2]=new cinemaTicket("245", "a23"); //error: cannot allocate an object of abstract type 'cinemaTicket' tList[3]=new cinemaTicket(); // error: cannot allocate an object of abstract type 'cinemaTicket for(int i=0;i<4; i++){ tList[i].printInfo(); } return 1; }

  • 仮想関数について困っています

    仮想関数について困っています C++を現在勉強中でその中で困ったことができました。 仮想関数についてまだ分かっていないことが多いのですが、一応以下のように使うものだと学びました。 class test{  public:   virtual void run(){    std::cout<<"testクラス"<<std::endl;   } }; class test_sub:public test{  public:   void run(){    std::cout<<"test_subクラス"<<std::endl;   } }; int main(){  test *t_s;  t_s=new test_sub;  t_s->run(); } ※includeは省略させていただきます こうすれば「test_subクラス」と出力されるはずです。 そこで本題なのですが自作のarrayクラスのようなものはテンプレートクラスになっているのですが array<test*> data; data[0].run(); のように使うと「testクラス」と表示されてしまいます。 これを解決する方法は何かないでしょうか? ご存じの方がいましたら教えていただけると助かります。

  • C#における++演算子のオーバーロードについて

    はじめまして。 いろいろ調べてみたのですが、わからなかったので、質問させてください。 C#における++演算子のオーバーロードについてなのですが、 まずは、以下のコードをご覧ください。 ================================================================ using System; class Test { private int Num; public Test(int x) { this.Num = x; } public static Test operator ++(Test t) { Test result = new Test(t.Num + 1); return result; } public override string ToString() { return this.Num.ToString(); } } class TestDemo { public static void Main() { Test t = new Test(0); Console.Write(t++ + "\n"); Console.Write(t + "\n"); Console.Write(++t + "\n"); Console.Write(t + "\n"); } } ================================================================ 実行結果 0 1 2 2 ================================================================ ++演算子のオーバーロード関数の実装が一つなのに 前置インクリメントと後置インクリメントが適切に行われています。 二つのインクリメントが行われるときに同じメソッドが 呼び出されていると思うのですが、同一の実装で、振る舞いが 異なるのは、なぜなのでしょうか?どのようなカラクリで 実行されているのでしょうか?全くわかりません。どなたか 教えてください。よろしくお願いします。

専門家に質問してみよう