如何创建一个抽象类的动态数组?

14

假设我有一个抽象类Cat,它有几个具体的子类,例如野猫、家猫等。

我希望我的数组能够存储指向某种类型的猫的指针,而不知道它到底是哪种类型。

当我尝试动态分配一个Cat数组时,似乎并没有起作用。

Cat* catArray = new Cat[200];
5个回答

22

通过创建指向 Cat 的指针数组,就像这样:

 Cat** catArray = new Cat*[200];

现在你可以将WildCat、HouseCat等实例放置在数组的各个位置,例如:

 catArray[0] = new WildCat();
 catArray[1] = new HouseCat();
 catArray[0]->catchMice(); 
 catArray[1]->catchMice();

需要注意以下几点:
a) 在完成任务后别忘了删除catArray中分配的实例,如delete catArray[0]等。
b) 别忘了使用delete删除catArray本身。

 delete [] catArray;

你还应考虑使用向量来自动化b)


7

您需要创建一个指向 Cat 的指针数组:

Cat** catArray = new Cat*[200];

即使基类 Cat 是具体类,如果你创建了一个 Cat 数组,仍然会遇到对象切片问题
请注意,你应该使用 std::vector 替代数组,并且应该使用智能指针来确保你的代码是异常安全的。

4

你不能在固定大小的笼子里圈养猫,因为编译器无法知道猫的大小,也不知道如何初始化它们(隐喻失败)。你需要将数组初始化为空猫指针或其他方式,并稍后再进行操作。


0

你不能直接实例化一个抽象类的实例,而必须实例化一个完全实现了的子类的实例。

所以这是合法的:

Housecat* theCats = new Housecat[200];

然后你可以通过Cat接口访问每只猫

bool catsMeow = ((Cat*)(&theCats[0]))->CanMeow();

但编译器无法知道如何实例化抽象类;事实上,它是抽象的意味着它不能直接被实例化。

为什么要这样做?因为Cat将有一个抽象方法。

bool CanMeow() = 0;

所有继承自猫的类都必须实现。然后你可以询问它是否能喵喵叫,有可能狮子的实例会返回false。


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++)),但我认为它可能与这里的主题相关,因为当我搜索时,这篇文章是我找到的最接近我的问题的文章。

实际上,似乎存在内存大小不匹配的问题。正在努力解决。 - Kaleb Coberly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接