有没有办法在容器中插入抽象类?第
有没有办法让基类访问派生类?使用虚函数。
有没有办法使这个示例代码正常工作,控制台 bark ?
有没有办法让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 :(得分:2)
有没有办法在容器中插入抽象类?
没有。但是您可以插入指向抽象类的指针(最好是智能指针)
这个示例代码是否有办法正常工作,控制台可以吠叫?
除非你愿意使用指针:否则,吠叫代码would be sliced off。
向量容器是否有办法保留实例而不是引用/指针?
您可以在容器中保留指针,但不能保留引用。但是,一旦在类中指向了您分配的对象或指针的整个向量,代码的复杂性就会提高,因为您必须遵循the rule of three。
如果我对实例使用引用计数器,那么在
std::vector
内存储指针只会是安全的,这是我的最后手段。我想念一下吗?
是的 - 您似乎缺少std::shared_ptr
,它会为您引用计数。您为此付出的小代价是必须使用std::shared_ptr
代替CZoo
中所有动物的简单指针。
答案 1 :(得分:1)
您可以使用std::unique_ptr
std::vector< std::unique_ptr<CAnimal> > zoo;
zoo.push_back(new CDog());
zoo[0]->soundsLike();
不好吗? unique_ptr将为您处理破坏。
我认为你不能使用参考文献。此外,我认为你现在不能让它“吠叫”。只有“woof”。
答案 2 :(得分: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
答案 3 :(得分:0)
问题是animalList只是基类CAnimal对象的向量。因此,您的编译器只保留足够的存储空间来保存CAnimal对象。由于虚函数的工作方式,由于查找表的要求,派生的CDog类总是需要比CAnimal类更多的存储空间。
由于您的CDog类没有足够的存储空间,因此对象的CDog部分会被切掉,只剩下对象的CAnimal部分。
使用指针传递对象是优先的,因为对象的地址始终具有相同的存储要求,因此您不会遇到任何对象切片问题。