2017-05-26 6 views
0

Angenommen, ich habe einen Code wie diesen, und ich möchte Zugriff auf die myClassB-Mitglieder erhalten. Wie kann ich das machen? Ich muss die Funktionalität von functionA verwenden. Ich kann es nicht ändern, weil es aus der 3rd-Party-Bibliothek stammt. Und ich muss functionA verwenden, um es zu erstellen und Werte von ihm zu erstellen. In diesem Fall "Test_1" stringWie bekomme ich Zugriff auf den abgeleiteten std :: shared_ptr?

class myClassA { 
public: 
    myClassA(){} 
    ~myClassA(){} 
}; 

class myClassB : public myClassA 
{ 
public: 
    myClassB(){} 
    void setString1(std::string newString) 
    std::string getS1()  
private: 
    std::string privateMember; 
}; 

std::shared_ptr<myClassA> functionA() 
{ 
    std::shared_ptr<myClassB> temporary(new myClassB()); 
    temporary->setString1("TEST_1"); 
    return std::move(temporary); 
} 

int main() 
{ 
    std::shared_ptr<myClassA> myPtr; // = functionA(); ?? 
} 
+0

Bewegung ist nicht erforderlich in Return-Anweisung. Clang wird sogar darüber beschweren. –

+0

Was ist mit dem Mitglied der Klasse A, können Sie es ändern? – Amadeus

+0

nein Ich kann nicht ich habe nur Zugriff auf die FunktionA – pZCZ

Antwort

3

Theoretisch könnte man ein dynamic_cast (oder in diesem Fall benutzt speziell std::dynamic_pointer_cast den abgeleiteten Zeigertyp zu erhalten, wie so:.

std::shared_ptr<MyClassA> a_ptr = functionA(); 
std::shared_ptr<MyClassB> b_ptr = std::dynamic_pointer_cast<MyClassB>(a_ptr); 
if(b_ptr) {//Check to verify the cast was successful 
    b_ptr->setString("Test1"); 
} 

Es gibt jedoch Ein wichtiger Vorbehalt dazu: Damit dynamic_cast (und damit std::dynamic_pointer_cast) funktionieren kann, muss in Ihrer Objekthierarchie eine virtuelle Tabelle definiert sein. Das bedeutet, dass mindestens eine der von MyClassA definierten Methoden als virtual deklariert sein muss Deklarieren Sie den Destruktor virtual, da dies immer dann sinnvoll ist, wenn Sie polymorphe Objekte definieren (da Sie es benötigen, um sicherzustellen, dass alle abgeleiteten Klassen ihre Ressourcen korrekt bereinigen).

class MyClassA { 
public: 
    MyClassA() = default; 
    virtual ~MyClassA() = default; 
}; 
+0

Vielen Dank für Ihre Antwort, aber ich muss FunktionA verwenden, um Zeiger zu erstellen – pZCZ

+0

@pZCZ Das ist in Ordnung. 'std :: make_shared' ist nur syntaktischer Zucker für was' functionA' in seiner ersten Codezeile tut. – Xirema

+0

immer noch, weiß nicht, wie man Werte von FunktionA erhalten, in diesem Fall muss ich "TEST_1" -String bekommen. Tut mir leid, dass ich nicht zu spezifisch bin. – pZCZ

1

mit dynamic_cast Zustimmen aber ohne eine virtuelle Funktionstabelle in KlasseA, so etwas wie dies zu tun haben würde:

Test This Code

#include <string> 
#include <memory> 
#include <iostream> 
#include <set> 

class myClassA { 
public: 
    myClassA(){} 
    ~myClassA(){} 
}; 

class myClassB; 
class ClassB_Registry{ 
    private: 
    ClassB_Registry(){ 
    } 
    ~ClassB_Registry(){ 
    } 
    public: 
    static ClassB_Registry* Get(){ static ClassB_Registry obj; return &obj; } 
    static void Register(myClassB* ptr){ 
     Get()->mPointers.insert(ptr); 
    } 
    static void UnRegister(myClassB* ptr){ 
     Get()->mPointers.erase(ptr); 
    } 
    static myClassB* Cast(myClassA* ptr){ 
     if(Get()->mPointers.count((myClassB*)ptr) > 0) return (myClassB*)ptr; 
     return nullptr; 
    } 

    private: 
    std::set<myClassB*> mPointers; 
}; 



class myClassB : public myClassA 
{ 
public: 
myClassB(){ ClassB_Registry::Register(this); } 
~myClassB(){ ClassB_Registry::UnRegister(this); } 
void setString1(std::string newString){privateMember = newString;} 
std::string getS1() { return privateMember; } 
private: 
std::string privateMember; 
}; 

std::shared_ptr<myClassA> functionA() 
{ 
std::shared_ptr<myClassB> temporary(new myClassB()); 
temporary->setString1("TEST_1"); 
return std::move(temporary); 
} 

int main() 
{ 
std::shared_ptr<myClassA> myPtr = functionA(); //?? 
std::shared_ptr<myClassA> myPtr_a(new myClassA()); //?? 
myClassB* pDerrived = ClassB_Registry::Cast(myPtr.get()); // bridge the RTTI gap 
if(pDerrived) 
    std::cout << pDerrived->getS1(); 

pDerrived = ClassB_Registry::Cast(myPtr_a.get()); // works on A pointers to return null 
if(pDerrived) 
    std::cout << pDerrived->getS1() << " \n"; 
else 
    std::cout << "Not A Pointer of Type B" << " \n"; 
} 

Es ist nicht schön ist, aber wenn myClassB hatte einen virtuellen Tisch Wie bereits erwähnt, und alle zukünftigen abgeleiteten Klassen verwendet myClassB als Basis, dann könnten Sie die Lücke für RTTI überbrücken.

Verwandte Themen