ATL-Styleクラス(テンプレートベースクラス)定義のAVエラー
次に、典型的なATLスタイルのクラス定義を示します.
このコードは非常に惑わされ、完全に正しいように見えますが、コンパイルすると、エラーメッセージが表示されます:error C 2248:'D 2::PrintClassName':cannot access protected member declared in class'D 2'、つまりD 2::PrintClassNameメソッドにアクセスする際に、十分な権限がありません.
修正方法は簡単で、D 2::PrintClassNameの方法をpublicで修飾するだけです.
原因を分析するのも簡単で、しかもとても面白いです.d 1を呼び出す.SayHiはd 1のため問題ない.SayHiメソッドによって呼び出されたPrintClassNameメソッドは派生クラスD 1によって書き換えられず、依然としてB 1のPrintClassNameメソッドであり、SayHiメソッドと同じタイプのthisポインタを持つ.すなわち、それらは同じクラスに定義され、クラスメソッドが同類メソッドを呼び出すのは常に成功する.B 1::PrintClassNameメソッドをprivateに変更しても、正しいです.
同様に、d 2が呼び出される.SayHiに問題が発生します.原因はd 2です.SayHiメソッドによって呼び出されたPrintClassNameメソッドは派生クラスD 2によって書き換えられており、両者のthisポインタタイプはまったく異なる.すなわち、同じクラスに定義されていないため、権限チェックが必要です.
#include "stdafx.h"
#include "iostream.h"
template <class T>
class B1
{
public:
void SayHi()
{
T* pT = static_cast<T*>(this);
pT->PrintClassName();
}
protected:
void PrintClassName()
{
cout<<"This is B1";
}
};
class D1 : public B1<D1>
{
// No overridden functions at all
};
class D2 : public B1<D2>
{
protected:
void PrintClassName()
{
cout<<"This is D2";
}
};
int main(int argc, char* argv[])
{
D1 d1;
D2 d2;
d1.SayHi(); // prints "This is B1"
d2.SayHi(); // prints "This is D2"
return 0;
}
このコードは非常に惑わされ、完全に正しいように見えますが、コンパイルすると、エラーメッセージが表示されます:error C 2248:'D 2::PrintClassName':cannot access protected member declared in class'D 2'、つまりD 2::PrintClassNameメソッドにアクセスする際に、十分な権限がありません.
修正方法は簡単で、D 2::PrintClassNameの方法をpublicで修飾するだけです.
原因を分析するのも簡単で、しかもとても面白いです.d 1を呼び出す.SayHiはd 1のため問題ない.SayHiメソッドによって呼び出されたPrintClassNameメソッドは派生クラスD 1によって書き換えられず、依然としてB 1のPrintClassNameメソッドであり、SayHiメソッドと同じタイプのthisポインタを持つ.すなわち、それらは同じクラスに定義され、クラスメソッドが同類メソッドを呼び出すのは常に成功する.B 1::PrintClassNameメソッドをprivateに変更しても、正しいです.
同様に、d 2が呼び出される.SayHiに問題が発生します.原因はd 2です.SayHiメソッドによって呼び出されたPrintClassNameメソッドは派生クラスD 2によって書き換えられており、両者のthisポインタタイプはまったく異なる.すなわち、同じクラスに定義されていないため、権限チェックが必要です.