2017-05-26 75 views
0

假設我有這樣的一個代碼,我想訪問myClassB成員。我怎樣才能做到這一點?我需要使用functionA的功能。 我無法更改它,因爲它來自第三方庫。我需要使用functionA來創建它,並獲取它創建的值。在這種情況下,「TEST_1」串如何訪問派生的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

舉動。鐺甚至會抱怨這件事。 –

+0

A班的成員怎麼樣,你可以改變它嗎? – Amadeus

+0

不,我不能我剛纔在泛函 – pZCZ

回答

3

從理論上講,你可以使用dynamic_cast(或在這種情況下,具體而言,std::dynamic_pointer_cast得到派生指針類型,像這樣:

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"); 
} 

有,但是,一個主要的警告了這一點。爲了dynamic_cast(因此std::dynamic_pointer_cast)的工作,你的對象層次結構必須定義一個虛擬表,這意味着由MyClassA定義的方法至少必須聲明virtual,最簡單的解決方法是宣佈破壞者virtual,因爲無論何時定義多態對象,這都是很好的做法(因爲您需要它來確保任何派生類都正確地清理其資源)。

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

謝謝您的回答訪問,但我需要使用泛函創建指針 – pZCZ

+0

@pZCZ這很好。 'std :: make_shared'只是函數A在其第一行代碼中執行的語法糖。 – Xirema

+0

還在,不知道怎麼弄的泛函在這種情況下,我需要得到「TEST_1」字符串設定的值。對不起,不具體。 – pZCZ

1

同意dynamic_cast但沒有ClassA的一個虛函數表,這樣的事情必須做的:

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"; 
} 

這不是很漂亮,但如果myClassB有虛表如前所述,所有未來派生類使用myClassB作爲基礎,那麼您可以彌補RTTI的差距。不需要在return語句

相關問題