所以我有5个班级,
我的Item类是一个抽象基类,cds,dvds和books都是从它派生的。 我的Inventory类有一个Items类型的指针数组,指向cd,dvd和books的对象。
这是数组:
Item* ptrItems[100];
int totalItems = 0`
以下是如何将对象分配给Inventory类中的数组:
ptrItems[totalItems++] = new books(1000 + totalItems, quantity, tempTitle,tempAuthor, tempDesc, cost);
//我使用总项目作为计数器来跟踪索引
我遇到的问题是ptrItems [totalItems]不能只访问Items抽象类的成员函数派生类的成员函数。
例如:
ptrItems[i]->getQuantity() //works fine because getQuanty is a member function of abstract base class Item.
然而,
ptrItems[i]->getBookTile() // won't work
error C2039: 'getBookTile' : is not a member of 'Item'
如果我错了,请纠正我但不是这种多态性?它应该可以访问派生类的公共成员函数,对吗?
答案 0 :(得分:2)
您需要先将Item *指针转换为Books *指针
Books * ptrBooks = dynamic_cast<Books*>(ptrItems[i]);
if(ptrBooks)
{
ptrBooks->getBookTitle();
}
检查ptrBooks的值是否为零非常重要,就好像传递给dynamic_cast的Item指针未指向Books对象一样,它将返回零。这是一种从基指针测试派生对象类型的方法。
答案 1 :(得分:2)
不,你要做的不是多态。它实际上与多态性完全相反。
多态性正在使用仅您的基类接口来操作派生类的任何,包括那些尚未编写的类。
例如,如果您希望项目具有标题,则在基类中定义虚拟(可能是纯粹的)方法getTitle()
,并在派生类中实现它。通过这种方式,您可以在不了解或关注其确切类型的情况下获取集合中任何项目的标题。
答案 2 :(得分:0)
我强烈建议重新考虑这个设计。多态性就是以同样的方式处理潜在的不同思想,你试图做相反的事情。有办法做到这一点,例如dynamic_cast
,但这通常表明设计不好,应该避免。
看起来您的对象或多或少是数据对象。作为第一步,尝试将操作分配给对象而不仅仅是返回某些成员变量的方法,例如getBookTile()
。然后,将这些服务的公共部分放在基类中,并使用通用实现中调用的抽象方法来提供特定于子类型的部分。
对于眼前的问题,如果你真的想这样做,一个解决方案就是使用dynamic_cast
:
dynamic_cast<books*>(ptrItems[i])->getBookTitle();
您可能还想查看std::vector
作为C风格数组的更好替代品。并通过一些智能指针替换普通指针,例如std::shared_ptr
或std::unique_ptr
,具体取决于您的所有权关系。
答案 3 :(得分:0)
项目无法知道每个项目是否都有方法getbookTitle()
,在这种情况下,它们似乎很清楚。假设您有一个项目数组,而不是所有项目都是书籍。然后你会遇到麻烦。由于这种不一致,在c ++中使用这种方法调用是不允许的。解决这个问题的方法是按照galinettes的说明进行动态投射。但是,您通常不希望在代码中执行此操作太多次。它会变得混乱,需要进行大量的额外检查(在这种情况下不必要,如您所见)。大量铸造的代码往往是某处设计缺陷的标志。
但是,在这种情况下,我可以假设所有对象都有标题。然后可以在基类中声明虚拟方法。
virtual string title() = 0; //Pure virtual
此方法必须在所有派生类中实现。现在可以在基类中看到该方法,并且从该基类派生的所有类都必须实现此方法。编译器知道该方法是虚拟的,因此将在类层次中搜索以找到正确的实现。现在可以调用
ptrItems[i] -> title();
可以在
中看到简短说明http://www.cplusplus.com/doc/tutorial/polymorphism/
此外,为了简化内存管理和更清晰的代码,除非您有充分的理由,否则更喜欢范围检查容器,例如std::vector
。