4

編集:明らかに、質問は明確に定式化されていません。私が抱えている問題は、デストラクタがヘッダーで定義されている場合、複数の .obj ファイルに追加され、リンカが文句を言うことです。実際の質問は次のとおりです。

DLL プロジェクトの CPP ファイルにデストラクタを追加し、動的読み込みとインターフェイス ヘッダー ファイルで dll を使用すると、メモリ リークを防ぐためにベース デストラクタが呼び出されますか?

MSVC 10.0 を使用しており、インターフェイスを実装する DLL プロジェクトがあります。インターフェイスは、抽象 (純粋仮想) 基本クラスです。アイデアは、ヘッダーがライブラリの動的ロードで使用されるということです。したがって、純粋な仮想デストラクタを使用して、基本クラスのデストラクタが確実に呼び出されるようにしました。これを説明するサンプル コードを次に示します。

//ISplitter.h
#pragma once

struct param {
    int something;
}

class ISplitter {
public:
    virtual ~ISplitter() = 0;
    virtual void useful() = 0;
}

ISplitter::~ISplitter() {
    /* Make sure base class destructor gets called */
}

そして、メインの実装ヘッダー

//CSplitter.h
#pragma once
#include "CHelper.h"
#include "ISplitter.h"


class CSplitter : public ISplitter {
private:
    CHelper hlp;
public:
    ~CSplitter();
    void useful();
}

一部のヘルパー クラス

//CHelper.h
#pragma once
#include "ISplitter.h" // I need the struct

// Class definition should go here but is irrelevant

ここでの問題は、リンカがデストラクタに通知するエラーを生成することです。ISplitter::~ISplitter(void) が複数宣言されており、システムがビルドされません。エラー:

CHelper.obj : error LNK2005: "public: virtual __cdecl ISplitter::~ISplitter(void)" (??1ISplitter@@UEAA@XZ) already defined in CSplitter.obj

これを修正する正しい方法は何ですか? ISplitter.cpp にデストラクタを配置しましたが、ライブラリを動的にロードして基本クラスを ISplitter にアップキャストすると、これが機能しないのではないかと心配しています。

4

2 に答える 2

6

問題は、基本クラスのデストラクタが常に呼び出されることですが、この場合は純粋仮想化されているため、存在しません。デストラクタを純粋仮想にする唯一の理由は、他のメンバーがいないときにクラスを強制的に抽象化することです。クラスのデストラクタは、すべての場合に定義する必要があります。

編集:コードを読み間違えました。デストラクタを事実上インラインで定義するだけです。

virtual ~ISplitter() {}

他の純粋仮想メンバーが既に存在するため、ここでは純粋仮想は必要ありません。

于 2011-05-30T10:02:46.483 に答える
3

Sharptoothの答えは、純粋な仮想デストラクタに定義を提供する必要があるという点で正しいです(このGotWを参照)。しかし、あなたが書くことができないという点で間違っています

virtual ~A() = 0 {};

標準のこの節によると(多くのコンパイラはこの拡張機能をサポートしていますが)

C ++ 03の10.4項の段落2は、抽象クラスとは何か、そして補足として、次のことを示しています。

[注:関数宣言は、純粋な指定子と定義の両方を提供することはできません—エンドノート] [例:

struct C {
virtual void f() = 0 { }; // ill-formed
};

-例を終了]

詳細については、私のこの質問を参照してください

于 2011-05-30T10:33:52.300 に答える