環境:Xcode 7.3.1(c++98)
virtual はオーバーライドする想定の関数につけるもの、と認識してます。
ですが実際のところ virtual の有無による挙動の違いがよく分かってなかったので実験しました。
実験
virtual 付けない例
Sample.h
// Log() はログ出力関数
class B
{
public:
void logA() { Log("logA in B"); };
void logB() { Log("logB in B"); };
};
class D : public B
{
public:
void logA() { Log("logA in D"); };
void logB() { Log("logB in D"); };
};
Sample.cpp
B b1 = D();
b1.logA();
B *b2 = new D();
b2->logB();
結果
logA in B
logB in B
基底クラス型、基底クラスポインタ型の変数に、派生クラス型のインスタンスを代入します。
関数はどちらも基底クラスのものが呼ばれています。
virtual 付ける例
class B
{
public:
virtual void logA() { Log("logA in B"); };
virtual void logB() { Log("logB in B"); };
};
class D : public B
{
public:
void logA() { Log("logA in D"); };
void logB() { Log("logB in D"); };
};
Sample.cpp
// virtual 付けない例と同じ
結果
logA in B
logB in D
基底クラス型、基底クラスポインタ型の変数に、派生クラス型のインスタンスを代入します。
ポインタの場合のみ派生クラスのものが呼ばれています。
考察
virtual がないと派生クラスの関数を考慮しないため B クラスのものが呼ばれるのは想定内。
一方で virtual つけてもポインタでないと呼ばれないのは考えてなかったです。
が、考えてみれば実体である以上それと異なるクラスの処理なんて扱えないですね。