在派生类中重新定义typedef?

时间:2011-09-13 06:24:57

标签: c++ inheritance override virtual typedef

因此,经过大量搜索我的问题的答案后,我终于放弃了我的Google技能。

我有一个基类基础,以及一个派生类派生。我想覆盖 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').

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

我也无法从同一个基类派生苹果和橘子,以在基础派生中返回其父类的指针/引用。我需要物理地返回对象的实例。

  1. 有什么方法可以声明抽象typedef?
  2. 如果没有,是否有任何其他解决方案可以实现我的目标 试图做什么?

4 个答案:

答案 0 :(得分:7)

首先,看看这个语法:

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

什么是override?在C ++ 03中,没有这样的关键字。它只在C ++ 11中。因此,请确保您使用的是知道此关键字的编译器。

其次,在派生类中,fruit确实是Orange。重新定义typedef不是问题。问题是,OrangeApple不是协变类型。从另一个中获取将使它们变得协变。在您的情况下,您必须从Orange派生Apple才能使其有效。

请注意,您必须更改fruitfruit*fruit&的返回类型。

class Orange : public Apple {}; //correct - your code will work

class Apple : public Orange {}; //incorrect - your code will not work

这个想法是,在基类中,返回类型应该是基类型的指针/引用(即Apple),并且在派生类中,返回类型可以是 Apple类型的指针/引用或任何派生自它的类。

顺便问一下,这有意义吗?从Orange获取Apple

以下课堂设计怎么样?

class Fruit {};
class Apple : public Fruit {};
class Orange : public Fruit {};

class Base
{
   virtual Fruit* f();
};

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

无需使用typedef

答案 1 :(得分:1)

开始时没有多大意义。 Derived应该能够在预期Base的任何地方使用,所以你应该能够做到

Base *foo = new Base();
Apple x = foo->func();   // this is fine

Base *bar = new Derived();
Apple y = foo->func();   // oops...

我认为你需要研究一个不同的设计。目前还不清楚你的目标是什么,但我猜你可能希望Base成为一个以Fruit作为模板参数的类模板,或者你可能需要摆脱继承共

答案 2 :(得分:0)

你真的不能这样做,如果你有一个价值对象,你必须知道它是哪种类型。 (这是静态类型语言(如C ++)和动态类型语言(如Ruby和Python)之间的主要差异之一。)

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

另一个解决方案,您的函数可以使用指针或引用Fruit,而不是返回值,然后可以填充。

另一种解决方案是拥有某种容器对象,内部可容纳Apple或Orange。这样你可以退货。

答案 3 :(得分:0)

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

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

实际上,您需要返回指针或引用才能执行此操作。

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

然后让func()返回Fruit*

这会让您在确定Fruit* delete时遇到问题。

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