3

Visual Studio 2008 C ++ 03プロジェクトがあり、宣言されたインターフェイスクラスがあります_declspec( novtable )。例えば:

class _declspec( novtable ) IFoo
{
public:
    virtual void FooDo() const = 0;
};

class Foo : public IFoo
{
public:
    ~Foo() { printf( "~Foo()\r\n" ); };
    void FooDo() const { printf( "FooDo()\r\n" ); };
};

int main( int argc, char* argv[] )
{
    IFoo* foo = new Foo();
    foo->FooDo();
    delete foo;
    return 0;
}

IFoo仮想デストラクタがないため、具象Fooデストラクタが呼び出されることはありません。

出力:

FooDo()

必要な出力:

FooDo()
~Foo()

しかし、MSDNでは、宣言されたインターフェイスクラスで関数を呼び出すことに対する悲惨な警告がありますnovtable。「novtableでマークされたクラスをインスタンス化してからクラスメンバーにアクセスしようとすると、アクセス違反(AV)が発生します。」したがって、virtual ~IFoo() { };メンバーを追加することは悪いことのように思えます。(私のテストでは、うまく機能しているようですが。)

これからどのようにして望ましい振る舞いを適切に得ることができますか?

4

1 に答える 1

6

インターフェイスクラスに仮想デストラクタを含めることは問題ありません。すでに別の仮想メソッドを含めて呼び出しているので、デストラクタも同じです。

の効果novtableは、のvtableがIFoo初期化されないことです。ただし、直接インスタンス化することはないので、問題ありませんIFoo。代わりに、そのクラスの子孫をインスタンス化します。子孫にはvtableがあり、そのvtableはのメソッドへのポインターで適切に初期化されますFoo(オーバーライドしない非純粋仮想メソッドがあるIFoo場合)。内部からの呼び出しは非仮想ディスパッチであるため、vtableはまだ必要ありません。IFooFoo~IFooFooIFoo

于 2012-05-17T17:46:16.523 に答える