その問題は 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 の開発者は最初からそうしなかったのでしょうか?