Effective C++T 07:多態ベースクラスに対してvirtual構造関数を宣言する


Effective C++学習ノート総リンク
プログラムと設計を改善する55の具体的な方法学習ノート-毎日1条
条項07:マルチステートベースクラスにvirtual構造関数を宣言する
【テクニック】
マルチステートプロパティbase classはvirtual構造関数を宣言する必要があります.classにvirtual関数がある場合は、virtual構造関数を持つ必要があります.
classの設計はbase classとして使用されるのではなく,あるいは多態性を備えるためにvirtual構造関数を宣言するべきではない.
base class virtual関数を持つvirtual構造関数を宣言する必要があります
【問題】base class(non-virtual構造関数)タイプのポインタがderived classオブジェクトを指して削除された場合、実際に実行すると通常発生するのはオブジェクトのderived成分が破棄されていないことです.
【結果】:奇妙な「ローカル破棄」対象をもたらします.これは、リソースの漏洩、破損したデータ構造を形成し、デバッガに多くの時間を浪費する絶好の方法です.
【方法】:base classにvirtual構造関数を与え、その後derived classオブジェクトを削除すると、すべてのderived class成分を含むオブジェクト全体が破棄されます.
virtual関数の目的はbase classインタフェースによるderived classオブジェクトの処理です
virtual関数実装
virtual関数を実装するには、オブジェクトが呼び出されるべきvirtual関数を決定するために主に使用される情報を携帯する必要があります.
この情報は通常、いわゆるvptr(virtual table pointer)ポインタによって指摘される.
vptrポインタは、vtbl(virtual table)と呼ばれる関数ポインタからなる配列を指す.
virtual関数を持つclassごとに対応するvtblがあります
オブジェクトがvirtual関数を呼び出すと、実際に呼び出される関数は、オブジェクトのvptrポインタが指すvtblに依存し、コンパイラは、適切な関数ポインタを探します.
classにvirtual関数が含まれていない場合は、virtual構造関数を宣言しないでください.
classがvirtual関数を含まない場合、通常はbase classとして使用されていないことを示し、その構造関数をvirtualにするのはよく悪い考えです.
【結果】
  • オブジェクトメモリ増加、オブジェクト内増加vptrポインタメモリ
  • は移植性を持たなくなった.このオブジェクトは、Cなどの他の言語内の同じ宣言と同じ構造(他の言語にはvptrがない)を持たないため、vptrを明確に補償しない限り、他の言語に書かれた関数を渡すことはできません.

  • テクニック:classに少なくとも1つのvirtual関数が含まれている場合にのみ、virtual構造関数を宣言します.
    標準コンテナ(STLコンテナ)またはnon-virtual構造関数を持つ他のclassを継承しようとしないでください.ローカル破棄が表示されます.
    pure virtual構造関数
    pure virtual関数はabstract(抽象)classをもたらし、実体化できないclassは、そのタイプのオブジェクトを作成できません.
    抽象classを望んでいる場合がありますが、pure virtual関数がありません.どうすればいいですか.
    抽象的なclassになることを望んでpure virtual構造関数を宣言します
    class AWOV
    {
         
    public:
    	virtual ~AWOV() = 0; //   pure virtual    
    };
    
    AWOV::~AWOV() {
          } // pure virtual       
    

    ただし、pure virtual構造関数の定義を指定する必要があります.【理由】:derived class構造関数が最初に呼び出され、base class構造関数が呼び出されます.~AWOVに対する呼び出し動作が作成されるので、この関数の定義が必要です.