虚関数について

2437 ワード

C++プログラマーであれば、このような状況に遭遇したことがあると思います.
Debugでは、1つの関数step intoに対して、A関数を呼び出したのに、結果的にB関数に飛び込んだ.
なぜか、call stackに表示されているのもはっきりしていて、B関数に直接入っています.よく考えられないので、システムに問題があったのではないかと疑っています.コンパイラに問題があったのではないでしょうか.デバッガに問題があったのではないでしょうか.
実はそれらのものはそんなに間違いやすいわけではありません.まず、あなたのA、B関数が同じクラスの虚関数であるかどうかを見てみましょう.もしそうであれば、これはあなたが虚関数を修正したため、完全にコンパイルしていない可能性が高いです.
まだわからないの?この例を見て、Project 1にDebuggingNowというクラスがあるとします.このクラスには3つの虚関数があります.
class DebuggingNow
{
public:
virtual void f1();
virtual void f2();
virtual void f3();
};

Project 2で虚関数を呼び出しました.
pDbgNow->f2();

その後、あるニーズでこのクラスに虚関数を追加しました.
class DebuggingNow
{
public:
virtual void f1();
virtual void f1_5();
virtual void f2();
virtual void f3();
};

Project 1のみをコンパイルし、Project 2でpDbgNow->f 2()を呼び出すと、本明細書で最初に説明したように、f 2()を呼び出すのにf 1_を入力していることがわかります.5().理由は次のとおりです.
pDbgNow->f 2()は、pDbgNow->vtable[1]と同様に実際に呼び出される虚関数であるため、呼び出しクラスDebuggingNowの2番目の虚関数としてコンパイルされていた.関数f 1_を入れる5()後、f 1_5はこのダミーテーブルの2番目の関数となったが、Project 2を再コンパイルしていないため、pDbgNow->f 2()の呼び出しが正しいpDgbNow->vtableに更新されていない[2]ため、本当に呼び出されたのは関数f 1_5()は、関数名に関係ありません.
このような「低級なエラー」はあなたには起こらないと思います.少なくとも2つの方法でこの問題を解決することができます.
  • は常に虚関数を最後の
  • に追加します.
  • すべてのプロジェクトを永遠にコンパイルする
  • 確かに、この2つの技はある程度有効ですが、よく分析してみましょう.
  • は常に虚関数を最後に加算し、上記の例に対して有用である.しかし、他のクラスがクラスDebuggingNowに派生している場合、クラスDebuggingNowの最後に虚関数を追加しても、その派生クラスの虚表が乱されます.
  • は、すべてのプロジェクトを永遠にコンパイルします.これは確かに保険の方法です.しかし、大規模なシステムでは、すべてのコードをコンパイルするのにかかる時間は非常に大きく、虚関数を追加すると、最後の結果を見るのに何時間も待たなければならないかもしれません.これは私たちが耐えられないことです.

  •  
    では、大規模なシステムの中で積極的な修正期間にあるコアベースクラスに対して、比較的良い操作方法は、十分な虚関数を事前に割り当てることです.このようにして、その後、虚関数を追加する必要があるのは、既存のものを修正すればいいので、大規模なrebuildを必要とせず、この虚関数を使用したコードをコンパイルするだけでいいのです.節約した時間はかなり大きいと言えます.
    class DebuggingNow
    {
    public:
    virtual void f1();
    virtual void f2();
    virtual void f3();
    virtual void dummyvirtualfunction1();
    virtual void dummyvirtualfunction2();
    virtual void dummyvirtualfunction3();
    virtual void dummyvirtualfunction5();
    virtual void dummyvirtualfunction6();
    };

     
    dummyvirtualfunctionを柔軟に運用すれば、虚関数を追加するだけでなく、虚関数を削除する際にもその役割を果たすことができます.
    2つの操作原則を覚えてください.
  • dummyvirtualfunctionが切れそうになったら、もう少し割り当てておきます.
  • この段階の開発が終了すると、このベースクラスは安定化し、余分なdummyvirtualfunctionを除去すればよい.