2017-11-17 3 views
1

Ich habe einige C-Strukturen, die durch einige Algorithmen verwendet werden, die C++ Teile miteinander verbinden.sicher dynamic_cast von c-Structure?

Am Eingabeende gibt es eine C++ - Struktur, die von der c-Struktur erbt, um einige Mitglieder hinzuzufügen. Am ausgangsseitigen Ende gibt es einige Komponenten, die diese Daten möglicherweise ebenfalls benötigen.

Gibt es einen sicheren Weg zu erkennen, ob diese C-Struktur tatsächlich die erwähnte C++ - Klasse ist? vielleicht, indem man c + + Kindklassen polymorph macht und dynamische Umwandlungen benutzt?

struct Cstruct{ 
    int someData; 
}; 


class CPPclass: public Cstruct{ 
    CPPclass(){}; 
    int someMoreData; 
}; 

so vielleicht so etwas wie

class CPPclass: public Cstruct{ 
    virtual ~CPPclass(){}; 
    CPPclass(){}; 
    int someMoreData; 
}; 

void test(Cstruct* i_c){ 
    auto cpp = dynamic_cast<CPPclass*>(i_c); // < does not work, because Cstruct is not polymorphic 
    if(cpp){ 
     // da; 
    } 
} 

aber vielleicht ?:

class CPPclassHelper: public Cstruct{ 
    virtual ~CPPclassHelper(){}; 
    CPPclassHelper(){}; 
    int someMoreData; 
}; 

class CPPclass: public CPPclassHelper{ 
    virtual ~CPPclassHelper(){}; 
}; 

void test(Cstruct* i_c){ 
    auto cpph = static_cast<CPPclassHelper*>(i_c); 
    auto cpp = dynamic_cast<CPPclass*>(cpph); 
    if(cpp){ 
     // da; 
    } 
} 
+1

werden, wenn Sie "C-Struktur" sagen, meinen Sie eine Struktur deklariert 'extern "C"' und verwendet in einige bestehende C-Bibliothek oder Schnittstelle, oder? Was kann aus Kompatibilitätsgründen nicht geändert werden? – Useless

+0

Wenn ich richtig verstehe, müssen Sie 'Cstruct' als C-Code kompilieren, aber Sie wollen später bestimmen können, ob ein' Cstruct * 'tatsächlich auf ein' CPPclass'-Objekt verweist, das etwas wie 'dynamic_cast' verwendet? –

+0

@Useless 'extern" C "' hat keinen Einfluss auf Strukturdefinitionen. Es beeinflusst nur die Aufrufkonventionen der Funktionen –

Antwort

1

Sie könnten die Typ-Informationen selbst pflegen. Verwenden Sie einen statischen Satz aller Zeiger auf Cstruct, die die Basis von CPPclass sind. Fügen Sie die Basis in allen Konstruktoren CPPclass ein, und entfernen Sie in dem Destruktor. Safe Cast kann dann mithilfe eines Lookups in diesem Set implementiert werden. Hier

ein Beispiel:

struct CPPclass: Cstruct{ 
    CPPclass(){ 
     bases.insert(this); 
    }; 
    CPPclass(const CPPclass&){ 
     bases.insert(this); 
    }; 
    CPPclass(CPPclass&&){ 
     bases.insert(this); 
    }; 
    ~CPPclass(){ 
     bases.erase(this); 
    }; 

    static CPPclass* safe_cast(Cstruct* c) { 
     auto it = bases.find(c); 
     return it == bases.end() 
      ? nullptr 
      : static_cast<CPPclass*>(*it); 
    } 

private: 
    static std::unordered_set<Cstruct*> bases; 
}; 

Verbrauch:

int main() { 
    CPPclass cpp; 
    Cstruct c; 

    Cstruct* ptr_cpp = &cpp; 
    Cstruct* ptr_c = &c; 

    std::cout << CPPclass::safe_cast(ptr_cpp) << '\n'; // some address equal to &cpp 
    std::cout << CPPclass::safe_cast(ptr_c) << '\n'; // null 
} 
0

Eine Möglichkeit eigene ENUM könnte das Hinzufügen Art zu erfassen, für ex.

enum myStruct { 
    C_STRUCT = 0, 
    CPP_STRUCT 
}; 
struct Cstruct 
{ 
    int someData; 
    enum myStruct type; 
}; 

class CPPclass : public Cstruct 
{ 
public: 
    CPPclass() { type = CPP_STRUCT; } 
    enum myStruct GetType() { return type; } 
}; 

Wenn Sie type von Cstruct Zeiger überprüfen, könnte es C_STRUCT oder CPP_STRUCT

Cstruct c {0, C_STRUCT}; 
CPPclass cpp; 

Cstruct* ptr_c = &c; 
Cstruct* ptr_cpp = &cpp; 

cout << ptr_c->type << endl; 
cout << ptr_cpp->type << endl; 
Verwandte Themen