多态性c++,试图访问从抽象基类派生的类的成员函数

polymorphism c++, trying to access member functions of classes that are derived from abstract base class

本文关键字:派生 基类 函数 成员 抽象 c++ 访问 多态性      更新时间:2023-10-16

所以我有5个类,

  1. cd
  2. dvd
  3. 书籍
  4. 项目
  5. 库存

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_ptrstd::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这样的范围检查容器。