C++での継承とオーバーロードの名前解決の問題
以下の様なプログラムを書いたのだがなぜかオーバーロードがうまくいかない...
#include<iostream> class Hoge{ public: void func(){ std::cout <<"パラメータなし"<<std::endl; } }; class Foo : public Hoge{ public: void func(int a){ std::cout <<"パラメータあり 値:"<< a <<std::endl; } }; int main(){ Foo obj; obj.func();//エラー }
ちょっと悩んでしまった。そういえばと思いだしExceptional C++を引っ張りだしてみるとあった。どうやらpublic継承でも隠蔽されてしまいオーバーローされないっぽい。どうしてもこれをしたい場合解決方法としてはusingとして関数を持ち込んでやる、つまり
class Foo : public Hoge{ public: //これを入れる using Hoge::func; void func(int a){ std::cout <<"パラメータあり 値:"<< a <<std::endl; } };
としてやることでうまくオーバーロードがなされる。
一見あれな仕様だが、
#include<iostream> #include<string> class Hoge{ public: void func(const char*){ std::cout <<"継承元のメソッド"<<std::endl; } }; class Foo : public Hoge{ public: void func(std::string){ std::cout << "呼びたいメソッド" <<std::endl; } }; int main(){ Foo obj; obj.func("hoge"); }
この実行結果は「呼びたいメソッド」と出力される。
一方using宣言を用い継承元のほうにあってもオーバーロードされるようにしてしまうと
#include<iostream> #include<string> class Hoge{ public: void func(const char*){ std::cout <<"継承元のメソッド"<<std::endl; } }; class Foo : public Hoge{ public: using Hoge::func; void func(std::string){ std::cout << "呼びたいメソッド" <<std::endl; } }; int main(){ Foo obj; obj.func("hoge"); }
実行すると「継承元のメソッド」と出力される。これはたぶん予期しない動作だろう。この例の場合一階層しかないのでいいが、これが言語仕様で保証されてるとするとかなり深い継承関係(そんなことはするべきでないという話はおいておいて)完全に一致する呼びたくないメソッドが呼ばれてしまい混乱してしまうだろう(たぶんそしてコンパイルエラーはでない)それなら、オーバーロードされず呼び出せないとコンパイルエラーを吐いてくれたほうが嬉しい気がする。
まだまだC++について全然理解してない...こういう細かい所でハマるのは無くしたい