1

クラスでのdllimportの使用に混乱しているので、助けていただければ幸いです。次のC++コードをビルドし、動的ライブラリにパッケージ化しました。

class __declspec(dllexport) normaldog {
    normaldog(){};
    ~normaldog(){};
    char* call() { return "woof!"; }
}

class __declspec(dllexport) stupiddog {
    stupiddog(){};
    ~stupiddog(){};
    char* call() { return "meow?"; }
}

ここで、通常のクラスと同じように、メインプログラムでこれらのクラスの1つ(インスタンス化、メソッドの呼び出し、破棄)を使用したいと思います。私の問題は、実行前にどちらを使用するかわからないことです。最初のexecでnormaldogを呼び出し、2番目のexecでstupiddogを呼び出すことができます。コンパイルされたコードでこれのエイリアスを使用したいと思います。これは実行時に解決されます。

それを行う方法はどうですか?typedefが最善の策だと思いますが、それを使用するための正しい構文が見つかりません...

よろしくお願いします!

4

1 に答える 1

0

その問題は DLL とは関係ありません (実際のプログラムでクラスが定義されている場合も同様です)。

Typedef はあなたが望むものではありません。これは完全に静的な機能であるため、実行時に何かを解決するのには役立ちません。

あなたが望むのはポリモーフィズムです。両方のクラスが (おそらく抽象) 基本クラスから継承するようにします。

class __declspec(dllexport) Dog
{
public:
    Dog() {}
    virtual ~Dog() {}

    virtual const char* Call() = 0;
};

class __declspec(dllexport) NormalDog : public Dog
{
public:
    NormalDog() {}
    ~virtual NormalDog() {}

    virtual const char* Call() { return "woof!"; }
};

class __declspec(dllexport) StupidDog : public Dog
{
public:
    StupidDog() {}
    virtual ~StupidDog() {}

    virtual const char* Call() { return "meow?"; }
};

その後、インスタンス化するものを実行時に決定し、Dog ポインターを介して使用できます。

Dog* pDog;

if (...)
    pDog = new NormalDog();
else
    pDog = new StupidDog();

pDog->Call();

編集: DLL のクラスを変更できない場合は、次の回避策を使用できます。

class DogObject
{
public:
    DogObject() {}
    virtual ~DogObject {}
};

class NormalDogObject : public DogObject
{
private:
    NormalDog m_dog; // the DLL's NormalDog

public:
    NormalDogObject() {}
    virtual ~NormalDogObject() {}

    NormalDog& GetNormalDog() { return m_dog; }
    const NormalDog& GetNormalDog() const { return m_dog; }
};

class StupidDogObject : public DogObject
{
private:
    StupidDog m_dog; // the DLL's StupidDog

public:
    StupidDogObject() {}
    virtual ~StupidDogObject() {}

    StupidDog& GetStupidDog() { return m_dog; }
    const StupidDog& GetStupidDog() const { return m_dog; }
};

次に、dynamic_cast を使用して DogObject の実行時の型を調べ、そのメソッドを呼び出します。

DogObject* pDog;

if (...)
    pDog = new NormalDogObject();
else
    pDog = new StupidDogObject();

if ((NormalDogObject* pNormalDog = dynamic_cast<NormalDogObject*>(pDog)) != nullptr)
    pNormalDog->Call();
else if ((StupidDogObject* pStupidDog = dynamic_cast<StupidDogObject*>(pDog)) != nullptr)
    pStupidDog->Call();

もちろん、すべてのクラスが同じメソッドを持っている場合 (この例のように)、DogObject でそれらのメソッドを純粋仮想として宣言し、DLL のクラスのメソッドへの呼び出しを委譲することによって派生クラスにそれらを実装させることができます (基本的にすべてを独自のクラス階層)。なぜ DLL の開発者は最初からそうしなかったのでしょうか?

于 2013-02-28T19:58:13.787 に答える