C++ におけるテンプレート メンバー関数のオーバーロードと多重継承
-
13-12-2019 - |
質問
以下のコードの動作を観察していますが、これは簡単には説明できないため、理論をよりよく理解したいと考えています。この特定の状況をカバーするオンライン ドキュメント ソースや既存の質問が見つからないようです。参考までに、私は Visual Studio C++ 2010 を使用して次のコードをコンパイルして実行しています。
#include <iostream>
using namespace std;
struct Bottom_Class
{
template<typename This_Type>
void Dispatch()
{
// A: When this comment is removed, the program does not compile
// citing an ambiguous call to Print_Hello
// ((This_Type*)this)->Print_Hello();
// B: When this comment is removed instead, the program compiles and
// generates the following output:
// >> "Goodbye from Top Class!"
// ((This_Type*)this)->Print_Goodbye<void>();
}
void Print_Hello() {cout << "Hello from Bottom Class!" << endl;}
template<typename This_Type>
void Print_Goodbye() {cout << "Goodbye from Bottom Class!" << endl;}
};
struct Top_Class
{
void Print_Hello() {cout << "Hello from Top Class!" << endl;}
template<typename This_Type>
void Print_Goodbye() {cout << "Goodbye from Top Class!" << endl;}
};
template<typename Top_Type,typename Bottom_Type>
struct Merged_Class : public Top_Type, public Bottom_Type {};
typedef Merged_Class<Top_Class,Bottom_Class> My_Merged_Class;
void main()
{
My_Merged_Class my_merged_object;
my_merged_object.Dispatch<My_Merged_Class>();
}
テンプレート化されたメンバー関数とテンプレート化されたメンバー関数で動作が異なるのはなぜですか?テンプレート化されていないメンバー関数の場合?
コンパイラーは (テンプレート化された場合に) Bottom_Class::Print_Goodbye() ではなく Top_Class::Print_Goodbye() が適切なオーバーロードであるとどのように判断しますか?
よろしくお願いいたします。
解決
の中に Dispatch
方法、 This_Type
と同じです My_Merged_Class
. 。の My_Merged_Class
もっている 二 という名前のメソッド Print_Hello
, もちろん、コンパイラはそれらを区別するのに問題が発生します。
への呼び出し Print_Hello
で Dispatch
, 、テンプレートを置き換えると、次のようになります。
((My_Merged_Class*)this)->Print_Hello();
上記の置き換えが、曖昧さがある理由をよりよく理解するのに役立つことを願っています。同じ問題 すべき 実際に起こるのは Print_Goodbye
, しかし、使用しているコンパイラのバグによりそれが通過してしまう可能性があります。
他のヒント
両方のコメント(afaikが正しく)GCC 4.6.3でコンパイルエラーを生成します。マイクロソフトコンパイラが不正確なことをしている可能性があります。
➜ scratch g++ -O2 templ.cc
templ.cc: In member function ‘void Bottom_Class::Dispatch() [with This_Type = Merged_Class<Top_Class, Bottom_Class>]’:
templ.cc:42:48: instantiated from here
templ.cc:16:9: error: request for member ‘Print_Goodbye’ is ambiguous
templ.cc:22:10: error: candidates are: template<class This_Type> void Bottom_Class::Print_Goodbye()
templ.cc:30:10: error: template<class This_Type> void Top_Class::Print_Goodbye()
.