在派生类中重新定义类型定义

Redefining a typedef in derived class?

本文关键字:定义 类型 新定义 派生      更新时间:2023-10-16

所以在搜索了很多问题的答案后,我最终放弃了我的谷歌技能。

我有一个基类 base 和一个派生类 derived 。我想用派生类中的类型覆盖类中的类型。下面是一个例子:
class Apple {
public:
    Apple() { }
    // ...
};
class Orange {
public:
    Orange() { }
    // ...
};
class Base {
public:
    typedef Apple fruit;
    // ...
    virtual fruit func() { return Apple(); }
};
class Derived : public Base {
public:
    typedef Orange fruit;
    // ...
    fruit func() override { return Orange(); } // <-- Error C2555!
};

这段代码不起作用,它给出了

C2555 error ('Derived::func': overriding virtual function return type differs and is not covariant from 'Base::func').

以上是我尝试过的解决方案之一。我还尝试在中创建一个虚拟嵌套类,并在派生中重新定义,这也没有编译(它也非常混乱)。

我也不能从相同的基类派生出apple和Oranges来返回指向它们在 base Derived中的父类的指针/引用。我需要物理地返回对象的实例。

  1. 是否有任何方法可以声明抽象类型?
  2. 如果没有,是否有其他解决方案可以达到我的目的想做什么?

首先,看看下面的语法:

fruit func() override { return Orange(); }

override是什么?在c++ 03中,没有这样的关键字。它只在c++ 11中存在。确保你使用的编译器知道这个关键字。

第二,在派生类中,fruit确实是Orange。重新定义typedef不是问题。问题是,OrangeApple不是协变型。从一个推导出另一个会使它们协变。在您的情况下,您必须从Apple派生Orange才能使其工作。

注意您必须返回类型从fruit更改为fruit*fruit&

class Orange : public Apple {}; //correct - your code will work
class Apple : public Orange {}; //incorrect - your code will not work
这个想法是,在基类中,返回类型应该是基类类型(即Apple)的指针/引用,而在派生类中,返回类型可以是Apple类型的指针/引用或从它派生的任何类。

顺便问一下,这有意义吗?从Apple推导Orange ?

下面的类设计如何?

class Fruit {};
class Apple : public Fruit {};
class Orange : public Fruit {};
class Base
{
   virtual Fruit* f();
};
class Derived : public Base 
{
   virtual Fruit* f();
};

不需要使用typedef

这从一开始就没有多大意义。Derived应该能够在任何需要Base的地方使用,所以您应该能够执行

Base *foo = new Base();
Apple x = foo->func();   // this is fine
Base *bar = new Derived();
Apple y = foo->func();   // oops...
我认为你需要考虑一个不同的设计。这里不清楚您的目标是什么,但我猜您可能希望Base是一个类模板,Fruit作为模板参数,或者您可能需要完全摆脱继承。

你不能这样做,如果你有一个值对象,你必须知道它是什么类型。(这是静态类型语言(如c++)与动态类型语言(如Ruby和Python)之间的主要区别之一。)

有很多方法可以解决这个问题。首先,让我们假设AppleOragne有一个名为Fruit的公共基类。一种解决方案是使用new动态分配对象并返回一个Fruit指针。

另一个解决方案是,你的函数可以不返回一个值,而是接受一个指向Fruit的指针或引用,然后它可以填充这个指针或引用。

另一个解决方案是使用某种容器对象,其内部可以存放Apple或Orange。这样你就可以返回它

报告的错误告诉您所需要的一切。这意味着Derived方法中返回的类型需要从基方法中返回的类型派生出来。

这样,如果基方法被虚拟调用,返回的对象可以被视为基方法返回的对象。

实际上,你需要返回一个指针或引用来做这件事。

你需要做的是定义一个新的Fruit基类,并从它派生AppleOrange

然后让func()返回一个Fruit*

这将给您留下一个问题,即确保Fruit*在某些时候是delete 'd。

有了更多的上下文,我怀疑(可能是薄)模板是您所追求的解决方案,而不是继承。