假设我有一个抽象类Cat,它有一些具体的子类Wildcat,Housecat等。
我希望我的数组能够存储指向某种猫的指针而不知道它究竟是哪种。
当我尝试动态分配Cat数组时,它似乎无法正常工作。
Cat* catArray = new Cat[200];
答案 0 :(得分:19)
通过创建指向Cat的指针,如
Cat** catArray = new Cat*[200];
现在您可以将WildCat,HouseCat等实例放在数组中的不同位置,例如
catArray[0] = new WildCat();
catArray[1] = new HouseCat();
catArray[0]->catchMice();
catArray[1]->catchMice();
完成后几点需要注意 a)不要忘记删除catArray中分配的实例,如删除catArray [0]等 b)不要忘记使用
删除catArray本身 delete [] catArray;
您还应该考虑使用vector来自动化b)
答案 1 :(得分:6)
您需要创建一个指向Cat
的指针数组:
Cat** catArray = new Cat*[200];
即使基类Cat
具体,如果你创建了一个Cat
数组,你仍然可以直接进入object slicing。
请注意,您应该使用std::vector
而不是数组,并且应该使用智能指针来确保您的代码是异常安全的。
答案 2 :(得分:4)
你无法在固定大小的笼子里围捕猫,因为编译器无法知道猫的大小,也不知道(隐喻失败)如何初始化它们。你需要做一些事情,比如初始化数组以使猫指针或其他东西归零,然后再将它们放进去。
答案 3 :(得分:0)
您不能直接实例化抽象类的实例,而必须实例化完全实现的子类的实例。
所以这是合法的:
Housecat* theCats = new Housecat[200];
然后您可以通过Cat界面访问每只猫
bool catsMeow = ((Cat*)(&theCats[0]))->CanMeow();
但编译器无法知道如何实例化抽象类;事实上,它的抽象意味着它无法直接实例化。
为什么这样?因为Cat会有一个抽象的方法
bool CanMeow() = 0;
所有遗传的猫必须实施。然后你可以问它是否可以喵喵叫,狮子的实例可能会返回假。
答案 4 :(得分:0)
然后我在类似情况下所做的事情是遍历数组并将每个元素指向nullptr。这样,您可以轻松地检查是否已将派生类对象添加到插槽中或该插槽是否已打开。
Cat** catArray = new Cat*[200];
for(int i = 0; i < 200; i++){
catArray[i] = nullptr;
}
for(int i = 0; i < 200; i++){
if(catArray[i] != nullptr){
AddRealCat(...);
break;
}
}
我想知道是否有一种更简单的方法来检查指向抽象类的指针数组中的元素是否指向派生类的对象还是仅仅是一个抽象指针,而没有将该元素设置为nullptr。例如,标准库中是否有 bool IsObject(ObjectType * ptr)或其他内容?
而且,我想知道是否将每个元素设置为nullptr会带来任何潜在的问题,除了遍历数组并将它们设置为nullptr的计算成本之外。
我将其发布为一个独立的问题(Array of Pointers to an Abstract Class: to nullptr or not to nullptr (C++)),但我认为这可能与此处相关,因为该帖子与我在搜索时发现的最接近的问题。