2016-04-10 18 views
2

私は、多くのDLLで共有される基本抽象クラス(interface)を継承しています。各DLLには、オブジェクトを動的に作成してそのポインタを返すエクスポートされたファクトリシンボルがあります。 2つの異なるDLLが同じ抽象クラスから継承された同じ名前のクラスを持っているとどうなりますか? obj1obj2を意味dllを介したC++クラスの衝突

class foo 
{ 
public: 
    virtual void func()const=0; 
}; 

DLL1

class bar: public foo 
{ 
public: 
    virtual void func()const{ 
    std::cout << "From Dll1" << std::endl; 
    } 
}; 

DLL2

class bar: public foo 
{ 
public: 
    virtual void func()const{ 
    std::cout << "From Dll2" << std::endl; 
    } 
}; 

メイン

int main() 
{ 
    foo* obj1; 
    foo* obj2; 
    // load DLLs 
    // import factory 
    // call factory to initialize objects 
    obj1->func(); // output: "From Dll1" 
    obj2->func(); // output: "From Dll2" 
    return typeid(*obj1) == typeid(*obj2); 
} 

戻りtrueは両方instanです同じ階級から派遣されました。同様にtypeid(*obj1).name()typeid(*obj2).name()は同じ名前class barを返します。 RTTIを使用してこれらのオブジェクトを区別できる方法はありますか?DLL自体を制御することはできませんか?この場合、クラスにはUUIDを提供するメカニズムが必要ですか?

P.S. IInspectableは、オブジェクトを工場にマップできると述べています。しかし、もしインターフェイスがオブジェクトをコンパイルすることが許せば? DLLは、ファクトリについて認識していないため、異なるモジュールから返されたオブジェクトを区別することはありません。それが私がRTTIを使用したい主な理由です。

+1

* "import factory" *と言ったときは、すでに実装しているモジュールを提供する必要があります。関数ポインタとモジュールの間のマッピングを格納したくない場合は、[GetModuleHandleEx](https://msdn.microsoft.com/en-us/library)を呼び出して、いつでも関数ポインタからモジュールを取得できます。 /windows/desktop/ms683200.aspx)。 – IInspectable

+0

@IInspectableあなたの返信をありがとう!私はモジュール間でオブジェクトを複合することができるようにしたいと考えています。特定の種類のオブジェクトのみを受け入れるために、派生クラスの実装にはいくつかの制約があります。 – Ivars

+0

モジュールの境界を越えてCRTリソースを分散させることは、痛みの世界に入るための同義語です。あなたが得ることができるものですが、それは複雑さと勤勉さに関する親密な知識を必要とします。詳細については、[DLL境界を越えるCRTオブジェクトを渡す潜在的なエラー](https://msdn.microsoft.com/en-us/library/ms235460.aspx)を参照してください。あなたはCOMを再発明しているように見えますが、代わりにReal Thing™を使用してみませんか? – IInspectable

答えて

0

まず、この種の構成はrun time dynamically linking of your DLLsでのみ可能です。 load-time dynamic linkingを使用する場合、linkeはインポートライブラリ内の重複シンボルを識別します。したがって、標準のC++ではなく実装固有の動作になります。

HINSTANCE dll1Handle = LoadLibraryA("Test0410-1DLL1.dll"); 
HINSTANCE dll2Handle = LoadLibraryA("Test0410-1DLL2.dll"); 
fct f1, f2; 
foo *obj1, *obj2; 

if (dll1Handle == NULL || dll2Handle == NULL) { 
    cout << "Both DLL couldn't be uploaded!" << endl; 
} 
else { 
    f1 = (fct)GetProcAddress(dll1Handle, "myfactory"); 
    f2 = (fct)GetProcAddress(dll2Handle, "myfactory"); 

    if (f1 == NULL || f2 == NULL) { 
     cout << "Both factories couldn't be uploaded!" << endl; 
    } 
    else { 
     obj1 = f1(); 
     obj2 = f2(); 

     obj1->func(); 
     obj2->func(); 

     if (typeid(obj1) == typeid(obj2)) 
      cout << "Same type"<<endl; 
     else cout << "Different type" << endl; 
    } 
} 

MSVCによって生成されたコードは、両方が同じ型であることがわかります。しかし、この行動を保証するものはありません。

それはあなたがobj->funcのアドレスを取ることができない、ので、あなたは相対アドレスで、両方のクラスで同じになりますfoo::functake the addressに必要な、仮想関数のポインタを使用することも困難です。

あなたの構造はODRの制限にあり、実装固有の動作をベースに構築されているため、クラスを安全に区別する最も簡単な方法は、fooに自家製のバーチャルタイプ識別機能を設けることです例では、クラスとdllの名前を組み合わせます。