ネタ元 → 思想の違い
コンストラクタ内でvirutal function呼んだらどないなるかっちゅーお話。
class Base {
public:
Base() { initialize(); }
virtual void initialize() { ... } // [1]
};
class Derived : public Base {
public:
virtual void initialize() { ... } // [2]
};
C++ではvirtualであろうがお構いなしに基底側(つまり[1])が呼ばれ、
C#/Javaだと導出側(よーするに[2])が呼ばれます。
んでは、Base::initialize() が pure-virtual やったらどないなんねん? と。
#include <iostream>
class Base {
public:
Base() { initialize(); }
virtual void initialize() =0;
};
class Derived : public Base {
public:
virtual void initialize() { std::cout << "Derived::initialize\n"; }
};
int main() {
Base* p = new Derived();
delete p;
}
ーーー Visual C++ 2005
VC++8ではコンパイルされちゃいます。が、リンク時に
error LNK2019: 未解決の外部シンボル "
public: virtual void __thiscall Base::initialize(void) が関数
"public: __thiscall Base::Base(void)"で参照されました。
fatal error LNK1120: 外部参照 1 が未解決です。
つまりお構いなしにBase::initialize()を呼ぶんだけどpure-virtualだから
実体がみつからん、と。
んじゃーってんでpure-virtual-funcの実体(?)を定義してあげます:
// コレ追加
void Base::initialize() {
std::cout << "呼んだらアカンやん!\n";
}
するってーとリンクできちゃって、実行すると呼んだらアカンやん!だそうです。
ーーー Borland C++ 5.6.4
Borland C++BuilderX でコンパイルすると...
するっと呑んでリンクまでできちゃいます。
実行すると: Pure virtual function called と表示。
pure-virtual が呼ばれたときのハンドラが用意されてんですねー
ーーー g++ 3.2
Borland C++BuilderX にオマケでついてる g++ 3.2 (MinGW)だとコンパイルエラーです。
abstract virtual `virtual void Base::initialize()' called 行 5
pure-virtual呼ぶなやゴルァ! だそうです。
ーーー dmc 4.5
DigitalMars C++ 4.5 だとg++と同じくコンパイルエラー:
Error: 'Base::initialize' is a pure virtual function
無いもん呼んだらダメでしょ!? と。