2014-04-22 31 views
0

有沒有辦法在容器中插入抽象類?編號
有沒有基類訪問派生類的方法?使用虛擬功能。
有沒有辦法讓這個示例代碼正常工作,並將控制檯樹皮
有沒有辦法讓vector容器保持實例而不是引用/指針?在運行時使用繼承代碼選擇器

std::vector裏面存儲指針只會在我使用引用計數器的情況下才是安全的,這是我最後的手段。我想念什麼?

class CAnimal 
{ 
public: 
    virtual void soundsLike() 
    { 
     cout<<"Base function\n"; 
    } 
}; 

class CDog: public CAnimal 
{ 
public: 
    void soundsLike() 
    { 
     cout<<"Woof\n"; 
    } 
}; 

class CZoo 
{ 
public: 
    std::vector<CAnimal> animalList; 

    void addDog() 
    { 
     animalList.push_back(CDog()); 
    } 

}; 

控制檯輸出的基函數的消息:

int main(int argc, char* argv[]) 
{ 
    CZoo nationalPark; 
    nationalPark.addDog(); 
    nationalPark.animalList.front().soundsLike(); //Calls the base function. 
    return 0; 
} 
+0

「是否有插入容器內的抽象類的方式編號?」 =>不是直接的,但你完全可以用指針。 – JBL

+1

「有沒有辦法在容器中插入抽象類?No.」你爲什麼在第一句中提問,並在第二句中回答? xD – luk32

+0

@JBL使用帶指針的容器會產生訪問衝突。 CDog的析構函數也被調用。 – William

回答

1

你可以使用std::unique_ptr

std::vector< std::unique_ptr<CAnimal> > zoo; 
zoo.push_back(new CDog()); 
zoo[0]->soundsLike(); 

它是壞? unique_ptr將爲你處理破壞。

我不認爲你可以使用引用。此外,我認爲你目前不會讓它「吠叫」。只有「woof」。

+0

所有的答案都很棒,但你的答案非常簡單。我使用cv :: Ptr智能指針類,因爲我已經在我的項目中包含了opencv,並且我也不使用C++ 11(還)。 – William

2

是否有插入容器內的抽象類的方法嗎?

不可以,但你可以插入一個指向一個抽象類(最好是智能指針)

是否有此示例代碼正常工作的方式和吠叫控制檯?

不除非你願意去指針:否則,吠叫代碼would be sliced off

有沒有辦法讓矢量容器保持實例而不是引用/指針?

您可以將指針保留在容器中,但不能保留引用。但是,一旦你在你的類中有一個指針指向你分配的對象,或者是一個完整的指針向量,代碼的複雜度就會上升,因爲你必須遵循the rule of three

std::vector裏面存儲指針只會在我使用引用計數器的情況下才是安全的,這是我的最後手段。我想念什麼?

是的 - 它似乎是你缺少std::shared_ptr,它爲你做引用計數。您支付的小額費用不得不使用std::shared_ptr代替CZoo中所有動物的簡單指針。

0

問題是,animalList只是您的基類CAnimal對象的一個​​向量。所以你的編譯器只保留足夠的存儲來保存CAnimal對象。由於虛擬函數的工作方式,由於查找表要求,您的派生CDog類將始終需要比CAnimal類更多的存儲空間。

由於您的CDog類沒有足夠的存儲空間分配,對象的CDog部分會被切掉,只剩下對象的CAnimal部分。

使用指針傳遞對象是優先考慮的,因爲對象的地址總是具有相同的存儲要求,因此您不會遇到任何對象切片問題。

1

如果你真的想在容器中跳過存儲指針,這裏是一個實現「假虛擬」機制的解決方案。請注意,這隻有在您擁有C++ 11編譯器的豪華功能時纔有效。您將需要通過幫助功能(caller)調用虛擬方法,並使用一種方法(我們的案例爲makeNoice),該方法充當虛擬機制以通過該機制傳送所有虛擬呼叫。

#include <iostream> 
#include <vector> 
#include <functional> 
#include <utility> 

// forward declarations of the base class and a helper function 
class CAnimal; 
void caller(CAnimal* a); 

// base class with small extensions 
struct CAnimal { 
    CAnimal() { mf = std::bind(caller, this); } 
    virtual void soundsLike() { std::cout<<"Base function\n"; } 

    // this will act as a virtual function 
    void makeNoice() { mf(this); } 
    std::function<void (CAnimal*)> mf; 
}; 

// a helper function to call the real virtual function 
void caller(CAnimal* a) {a->soundsLike();} 

// the actual animals 
struct CDog: public CAnimal { 
    virtual void soundsLike() { std::cout<<"Woof\n"; } 
}; 
struct CCat: public CAnimal { 
    virtual void soundsLike() { std::cout<<"Miau\n"; } 
}; 

int main() 
{ 
    CDog dog; 
    CCat cat; 

    std::vector<CAnimal> animalList; 
    animalList.push_back(dog); 
    animalList.push_back(cat); 

    // calling the fake virtual 
    animalList[0].makeNoice(); 
    animalList[1].makeNoice(); 
} 

這裏是它ideone:http://ideone.com/MRDaZ3