使用基类中定义的函数返回指向派生类实例的指针时出现无效转换错误

Posted

技术标签:

【中文标题】使用基类中定义的函数返回指向派生类实例的指针时出现无效转换错误【英文标题】:Invalid conversion error on returning a pointer to instance of a derived class using function defined in the base class 【发布时间】:2014-02-15 01:06:19 【问题描述】:

这可能是一个微不足道的问题,但我正在尝试重新熟悉 C++,但在这里找不到解决方案。因此,我将不胜感激。

考虑以下链表中元素的实现:

class Item 
 public:
  void set_val(int val)  val_=val; 
  int get_val() const  return val_; 
  void set_next(Item* next)  next_=next; 
  Item* get_next() const  return next_; 
 private:
  int val_;
  Item* next_

现在考虑从中派生以下类:

class NewItem: public Item 
 public:
  void set_newval(int val)  newval_=val; 
  int get_newval() const  return newval_; 
 private:
  int newval_;

基本上,派生类增加了另一个值。让我们实例化以下对象:

NewItem* i1 = new NewItem;
NewItem* i2 = new NewItem;
i1->set_next(i2);

这工作没有任何错误。我还可以访问 val 和 newval。但是,以下行

NewItem* i3;
i3=i1->get_next();

产生错误

testprogram.cc:24:15: error: invalid conversion from ‘Item*’ to ‘NewItem*’ [-fpermissive]

我知道get_next() 方法正在返回一个指向基类的指针。有什么办法可以解决我的问题吗?也许我应该重新构建我的类声明?为每个新的派生类添加一个“next”指针似乎很浪费。重铸似乎很危险。有没有更优雅的解决方案??

【问题讨论】:

您如何确定get_next() 确实返回了NewItem 指针?没有什么能阻止我调用set_next 传递从Item 派生的任何奇数类。 如果您设置一个类来表示Item * 的列表,那么您应该通过Item * 接口访问它们。直接使用NewItem * 指针似乎违背了以这种方式设置列表的目的。这在很大程度上似乎只是一个糟糕的 OOP 设计。在这里,模板可能比继承更好。 @PaulGriffiths 好的,我现在看到这是一个糟糕的 OOP 设计,我现在看到模板在这里会更好(这样可以编写一个采用任意类型的链表,其中type 可以是一个包含你想要的任何东西的类,此外,还有重载的运算符,比如比较)。进一步思考你所说的让我搜索“继承与模板”,这在这个网站上带来了两个封闭的问题。上述已关闭问题的答案之一包含此链接:hackcraft.net/cpp/templateInheritance 似乎值得一读。 【参考方案1】:

问题是 Item 类中的 set_next 和 get_next 方法不是 在子 NewItem 类中被覆盖。您可以尝试将它们转换为这样的 Item 对象

i1->set_next((Item)i2);
NewItem* i3;
i3=(NewItem)(i1->get_next());

否则你需要覆盖它们

void set_next(NewItem* next)  next_=next; 
NewItem* get_next() const  return next_; 

编辑:我很抱歉我完全忘记了规范形式。

如果你的类中有指针,那么你需要编写一个复制构造函数。 这是因为当你在主语中说类似

Item a = b; // the copy constructor is called.

该类假定您想要一个浅拷贝,这意味着它将按原样复制所有成员变量 包括指针。 问题是您的 NewItem 对象需要与您的 Item 类不同的复制协议。

接下来,您需要编写一个析构函数,在其中删除类成员变量中的所有指针。在您的程序中,如果您在函数内创建 Item 的实例,则程序应取消引用任何指针,否则您将获得内存泄漏。

析构函数看起来像一个前面有波浪号的构造函数

~Item()delete next_;

Def 检查规范形式,因为如果你要包含它,你必须理解它 类中的指针。

还要记住包括';'在你的类定义结束时

例如:

class MyClass
    ...
    ...
;  // ';' needs to go at the end of the class def

【讨论】:

您的意思是投射到指针Item* 而不是对象本身Item?我考虑过,但这不是有点危险吗?我不认为覆盖 set_nextget_next 方法在我的情况下不起作用,因为你不能在继承类的定义中更改 next_ 的类型(我认为......)因此它将再次需要危险的铸造。 因为它被标记为 C++,所以我会避免使用 C 风格的转换。改为使用 dynamic_cast 向下转换。

以上是关于使用基类中定义的函数返回指向派生类实例的指针时出现无效转换错误的主要内容,如果未能解决你的问题,请参考以下文章

关于C++基类、派生类的引用和指针

虚函数和基类中的this指针的问题!

虚函数的调用

无法将指向派生类函数的指针传递给基类

为啥基类指针指向基类中的纯虚方法,而不是派生类中的覆盖方法?

基类指针指向派生类对象&派生类指针指向基类对象