よくある仮想関数を使ったポリモーフィズム(多様性)の例とは少し違うけど
(複数の種類の派生クラスのアドレスを、親クラスのポインタに代入するやつ)、
メソッドをオーバーライドした場合と、隠ぺいした場合の動作の違いを例示すると、
こんな感じのソースになる。
#include <iostream>
using std::cout;
using std::endl;
class CBase {
public:
void funcCall(char *c) {
cout << c << func01() << "," << func02() << endl;
}
virtual char *func01() {return " Base01";}
char *func02() {return " Base02";}
};
class CDerived : public CBase {
public:
char *func01() {return " Derv01";} // オーバーライド
char *func02() {return " Derv02";} // 隠ぺい
};
int main() {
CBase obj01;
CDerived obj02;
// [1]
obj01.funcCall("BaseClass:");
// [2]
obj02.funcCall("DervClass:");
// [3]
cout << "DervClass:" << obj02.func01() << "," << obj02.func02() << endl;
return 0;
}
obj01 は CBase クラスなので、当然 CBase の func01 と func02 の関数が呼ばれる。([1])
一方の obj02 は、 CDerived クラスだが、 funcCall 関数は CBase クラスのメソッドなので、
func01 と func02 を funcCall 関数から呼ぶと、
オーバーライドされている func01 は CDerived のものが呼ばれ、
単に同じ関数名で隠ぺいしているだけの func02 は、 CBase のものが呼ばれる。([2])
しかし、 obj02 の func01 と func02 を直接呼べば、両方とも CDerived のものが呼ばれる。([3])
つまるところ、 CDerived クラスの func02 関数は、
CDerived という新たなスコープで func02 関数が定義されているだけなので、
CBase というスコープ (funcCall 関数内からの呼び出し) からは CBase の func02 が呼ばれ、
CDerivedというスコープ (obj02 のメソッドとしての呼び出し) からはCDerivedのfunc02が呼ばれると言うわけだ。
ブロックスコープで例えてみるなら、以下のソースの出力が
// 元のスコープ
int a = 8;
{ // ブロックによる入れ子スコープ
int a = 16; // "元のスコープ"のa変数を隠ぺいする
cout << a << endl;
}
cout << a << endl;
16 8 |
となることに疑念はないだろう。
ピンバック: Aqua Ware つぶやきブログ » WM_SIZEをハンドルしないCDialogResizeを作る