虚析構造関数による議論
1974 ワード
今日同僚がcode reviewを手伝ってくれたとき、commentを言いました.なぜこのクラスの構造関数の前にvirtualを付けないのですか.多態構造の場合、親の構造関数が転勤しないのを防止しますか.
このクラスには他の虚関数もないし、他のクラスに継承させるつもりもないからだと説明します.もし構造関数の前にvirtualを追加しなければならないなら、このクラスは虚関数テーブルのポインタを維持しなければならないので、少し蛇足です.
次に同僚の答えも理にかなっている.もしこのクラスが引き継がれたら、ちょうど親のポインタで分析するのだろうか.
私の最初の反応は、それはすべてのC++のクラスに構造関数を追加するのではないでしょうか.後で反応して、いくつかの手段を利用して、この類を制限して、それが継承されることを許さないことができますか?
JAVAにはfinalというキーワードがあります.finalで修飾されたクラスやメソッドは継承に使用できません.C++は?資料を調べてみると、C++11にもfinalキーワードが導入されていて、同じ目的地に達していました.
しかし、私たちのこのプロジェクトは古いバージョンのC++で実行されています.これはどうすればいいですか?
派生クラスオブジェクトのインスタンス化では,まずベースクラスコンストラクタを呼び出し,ベースクラス部分オブジェクトを初期化した後,派生クラスコンストラクタを呼び出し,派生クラス部分オブジェクトを初期化することが知られている.派生クラスに呼び出されないように、単一のようにベースクラスの構造関数に手足を動かすことができますか?
その後、やはりStackoverflowで次の方法を見つけました.
上記のコードでは、class Deriveがclass Baseを継承しようとすると、コンパイルエラーが報告されます.error:‘CSealed::CSealed()’is protectedにより、class Baseの継承を禁止する目的を達成しました.
どうしてDeriveはCSealedのせいでBaseを継承できないのですか?ここで利用するダミー継承のメカニズムにより、DeriveはBaseを越えてCSealedのコンストラクション関数を直接呼び出さなければならないが、CSealedのコンストラクション関数はprotectedであるため、Deriveは呼び出す権限がなく、コンパイルエラーを引き起こす.また、BaseはCSealedから継承されるため、BaseはCSealedのコンストラクション関数にアクセスできます.
最後にまとめると、この問題自体がtrickyです.そのルーツはC++マルチステートの場合,クラスオブジェクトを解析する際に親クラスの非虚解析関数トラップは呼び出されないことである.この罠を踏まないように、コンパイラの範囲を制限するためにworkaroundをいくつか作りました.C++11にfinalキーワードが導入されるのも無理はありません.
このクラスには他の虚関数もないし、他のクラスに継承させるつもりもないからだと説明します.もし構造関数の前にvirtualを追加しなければならないなら、このクラスは虚関数テーブルのポインタを維持しなければならないので、少し蛇足です.
次に同僚の答えも理にかなっている.もしこのクラスが引き継がれたら、ちょうど親のポインタで分析するのだろうか.
私の最初の反応は、それはすべてのC++のクラスに構造関数を追加するのではないでしょうか.後で反応して、いくつかの手段を利用して、この類を制限して、それが継承されることを許さないことができますか?
JAVAにはfinalというキーワードがあります.finalで修飾されたクラスやメソッドは継承に使用できません.C++は?資料を調べてみると、C++11にもfinalキーワードが導入されていて、同じ目的地に達していました.
しかし、私たちのこのプロジェクトは古いバージョンのC++で実行されています.これはどうすればいいですか?
派生クラスオブジェクトのインスタンス化では,まずベースクラスコンストラクタを呼び出し,ベースクラス部分オブジェクトを初期化した後,派生クラスコンストラクタを呼び出し,派生クラス部分オブジェクトを初期化することが知られている.派生クラスに呼び出されないように、単一のようにベースクラスの構造関数に手足を動かすことができますか?
その後、やはりStackoverflowで次の方法を見つけました.
class CSealed {
protected:
CSealed() {}
};
class Base : virtual CSealed {
public:
Base() {}
~Base() {cout << "Base::~Base()" << endl;}
};
class Derive : public Base {
public:
Derive() {cout << "derive" << endl;}
};
上記のコードでは、class Deriveがclass Baseを継承しようとすると、コンパイルエラーが報告されます.error:‘CSealed::CSealed()’is protectedにより、class Baseの継承を禁止する目的を達成しました.
どうしてDeriveはCSealedのせいでBaseを継承できないのですか?ここで利用するダミー継承のメカニズムにより、DeriveはBaseを越えてCSealedのコンストラクション関数を直接呼び出さなければならないが、CSealedのコンストラクション関数はprotectedであるため、Deriveは呼び出す権限がなく、コンパイルエラーを引き起こす.また、BaseはCSealedから継承されるため、BaseはCSealedのコンストラクション関数にアクセスできます.
最後にまとめると、この問題自体がtrickyです.そのルーツはC++マルチステートの場合,クラスオブジェクトを解析する際に親クラスの非虚解析関数トラップは呼び出されないことである.この罠を踏まないように、コンパイラの範囲を制限するためにworkaroundをいくつか作りました.C++11にfinalキーワードが導入されるのも無理はありません.