次のコードでdaughter
型のオブジェクトをインスタンス化すると、デフォルトのgrandmother()
コンストラクターが呼び出される理由がわかりません。
grandmother(int)
コンストラクターを(私のmother
クラスコンストラクターの仕様に従うために)呼び出すか、仮想継承のためにこのコードをまったくコンパイルすべきではないと考えました。
ここでは、コンパイラーはgrandmother
デフォルトコンストラクターを黙って呼び出しますが、私はそれを要求しませんでした。
#include <iostream>
class grandmother {
public:
grandmother() {
std::cout << "grandmother (default)" << std::endl;
}
grandmother(int attr) {
std::cout << "grandmother: " << attr << std::endl;
}
};
class mother: virtual public grandmother {
public:
mother(int attr) : grandmother(attr) {
std::cout << "mother: " << attr << std::endl;
}
};
class daughter: virtual public mother {
public:
daughter(int attr) : mother(attr) {
std::cout << "daughter: " << attr << std::endl;
}
};
int main() {
daughter x(0);
}
仮想継承を使用する場合、仮想ベースクラスのコンストラクターは、最も派生したクラスのコンストラクターによって直接呼び出されます。この場合、daughter
コンストラクターはgrandmother
コンストラクターを直接呼び出します。
初期化リストでgrandmother
コンストラクターを明示的に呼び出していないため、デフォルトのコンストラクターが呼び出されます。正しいコンストラクターを呼び出すには、次のように変更します。
daugther(int attr) : grandmother(attr), mother(attr) { ... }
This FAQ entry も参照してください。