多态性c++,试图访问从抽象基类派生的类的成员函数
polymorphism c++, trying to access member functions of classes that are derived from abstract base class
所以我有5个类,
- cd
- dvd
- 书籍
- 项目
- 库存
My Item类是一个抽象基类,cd、dvd和书籍都是从中派生的。我的Inventory类有一个Items类型的指针数组,指向cd、dvd和书籍的对象。
这是阵列:
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'
如果我错了,请纠正我,但这不是多态性吗?它应该有权访问派生类的公共成员函数,对吧?
不,您要做的不是多态性。它实际上与多态性正好相反。
多态性仅使用基类接口来操作任何派生类,包括尚未编写的派生类。
例如,如果您希望您的项具有标题,则可以在基类中定义虚拟(可能是纯)方法getTitle()
,并在派生类中实现它。这样,你就可以在不知道或不关心其确切类型的情况下获得收藏中任何物品的标题。
您需要首先将Item*指针转换为Books*指针
Books * ptrBooks = dynamic_cast<Books*>(ptrItems[i]);
if(ptrBooks)
{
ptrBooks->getBookTitle();
}
重要的是要检查ptrBooks的值是否为非零,就像传递给dynamic_cast的Item指针没有指向Books对象一样,它将返回零。这是一种从基指针测试派生对象类型的方法。
我强烈建议重新考虑设计。多态性就是以同样的方式处理潜在的不同想法,而你却试图做相反的事情。有一些方法可以做到这一点,例如dynamic_cast
,但这通常是糟糕设计的标志,应该避免。
看起来您的对象或多或少都是数据对象。作为第一步,尝试将操作分配给对象,而不仅仅是返回某些成员变量(如getBookTile()
)的方法。然后,将这些服务的公共部分放在基类中,并使用公共实现中调用的抽象方法来提供子类型特定的部分。
对于眼前的问题,如果你真的想这样做,一个解决方案是使用dynamic_cast
:
dynamic_cast<books*>(ptrItems[i])->getBookTitle();
您可能还想签出std::vector
作为C样式数组的更好替代品。根据您的所有权关系,用一些智能指针替换普通指针,例如std::shared_ptr
或std::unique_ptr
。
Item无法知道是否每个Item都有方法getbookTitle()
,在这种情况下,很明显他们没有。假设您有一个Items数组,并且并非所有Items都是Book。那样你就会遇到麻烦。由于这种不一致性,在c++中不允许使用这样的方法调用。解决这一问题的方法是按照galinettes的回答进行动态铸造。但是,您通常不希望在代码中多次执行此操作。它会变得很乱,需要大量的额外检查(在这种情况下是不必要的,正如你所看到的)。带有大量铸造的代码通常是某个地方存在设计缺陷的标志。
但是,在这种情况下,我可以假设所有对象都有一个标题。然后可以在基类中声明一个虚拟mehtod。
virtual string title() = 0; //Pure virtual
这个方法必须在所有派生类中实现。现在可以在基类中看到该方法,并且从该基类派生的所有类都必须实现该方法。编译器知道该方法是虚拟的,因此会在类层次结构中搜索以找到正确的实现。现在可以调用
ptrItems[i] -> title();
在中可以看到简短的描述
http://www.cplusplus.com/doc/tutorial/polymorphism/
此外,为了简化内存管理并获得更干净的代码,除非有充分的理由,否则最好使用std::vector
这样的范围检查容器。
- 如何通过派生类函数更改基类中的向量
- 如何使用基类指针引用派生类成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何引用基类的派生类?
- 如果基类包含双指针成员,则派生类的构造函数
- 为什么此派生对象无法访问基类的后递减方法?
- 使用基类中的派生方法运行线程,而无需使用模板
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- 在派生类中使用基类的私有成员变量的最佳方法
- 基类和派生类的多态赋值运算符
- 如何在从抽象基派生的类中实现相同的方法?
- 基类的填充将被复制到派生类中
- 如何在不使用指针的情况下将派生类的对象作为参数传递给基类中的函数?
- 指向基类派生类的 std::unique_ptr 的指针
- 为什么基类数据在派生类数据之前初始化
- c++ 派生基类 Friend 函数访问父级上的私有函数
- 如何将基类替换为派生基类
- 当基类未指定构造函数时,如何使用仅具有带参数的构造函数的类派生基类?
- 解析公用派生基类模板中的函数模板名称时出错"Not declared in this scope"