【问题标题】:Redefining a typedef in derived class?在派生类中重新定义 typedef?
【发布时间】:2011-11-15 21:26:37
【问题描述】:

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

我有一个基类 Base 和一个派生类 Derived。我想用 Derived 类中的一个覆盖 Base 类中的一个类型。这是一个例子:

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中重新定义,结果也没有编译(也很乱)。

我也不能从同一个基类派生 Apples 和 Oranges 来返回指向它们在 BaseDerived 中的父类的指针/引用。我需要物理返回该对象的一个​​实例。

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

【问题讨论】:

    标签: c++ inheritance overriding virtual typedef


    【解决方案1】:

    首先,看看这个语法:

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

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

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

    请注意,您必须将返回类型从fruit更改fruit*fruit&amp;

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

    思路是,在基类中,返回类型应该是基类型(即Apple)的pointer/reference,而在派生类中,返回类型可以是Apple 或任何派生自它的类的 em>指针/引用。

    顺便说一句,这有意义吗?从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

    【讨论】:

    • override 关键字通过让编译器检查函数是否实际上覆盖了任何基本方法来帮助消除人为错误(如拼写错误)。至于这个问题,我是知道的。有什么方法可以让它们在不使用指针或引用的情况下实现协变?
    • 所以我想没有解决方案可以使这项工作。谢谢,人们。我会尝试使用不同的层次结构。
    【解决方案2】:

    你不能真正做到这一点,如果你有一个值对象,你必须知道它是哪种类型。 (这是 C++ 等静态类型语言与 Ruby 和 Python 等动态类型语言之间的主要区别之一。)

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

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

    另一种解决方案是使用某种容器对象,该对象在内部可以容纳 Apple 或 Orange。这样你就可以退货了。

    【讨论】:

      【解决方案3】:

      一开始这没有多大意义。 Derived 应该可以在任何需要 Base 的地方使用,所以你应该可以这样做

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

      我认为您需要研究一种不同的设计。目前尚不清楚您的目标是什么,但我猜您可能希望 Base 成为具有 Fruit 作为模板参数的类模板,或者您可能需要完全摆脱继承。

      【讨论】:

        【解决方案4】:

        报告的错误会告诉您所需的一切。意思是Derived方法返回的类型需要从基方法返回的类型派生出来。

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

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

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

        然后让func() 返回Fruit*

        这会给您留下确保Fruit* 在某些时候是delete 的问题。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-02
          • 2012-01-12
          • 2015-05-20
          相关资源
          最近更新 更多