为从DLL导入的未知C ++类定义别名

时间:2013-02-28 18:54:14

标签: class dll alias typedef

我对在课堂上使用dllimport感到困惑,并希望得到一些帮助! 我构建了以下C ++代码并将其打包为动态库:

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

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

现在,我想在我的主程序中使用其中一个类(实例化,调用方法和销毁),就像我使用普通类一样。我的问题是,我不知道在运行之前我将使用哪一个:我可以在第一个exec上调用 normaldog ,然后在第二个exec上调用 stupiddog 。我想在我的编译代码中使用别名,这将在运行时解析。

如何做到这一点?我会说 typedef 是我最好的选择,但我找不到使用它的正确语法...

提前感谢您的帮助!

1 个答案:

答案 0 :(得分: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的开发人员最初没有这样做呢?