2011-09-13 35 views
6

因此,在搜索了很多关于我的问题的答案后,我终于放弃了我的Google技能。重新定义派生类中的typedef?

我有一个基类基地,和派生类派生。我想覆盖基类类中的类型,其中派生类中的一个。这里有一个例子:

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'). 

上面是解决我尝试之一。我也尝试在基地中创建虚拟嵌套类,并在衍生重新定义,并且也没有编译(这也非常混乱)。

我也不能导出苹果和桔子从同一基类的指针/参考返回到它们的父类中基地派生。我需要物理返回对象的一个​​实例。

  1. 有没有什么办法可以声明抽象typedefs?
  2. 如果没有,是否有任何其他解决方案可以实现我想要做的 ?

回答

6

首先,看这个语法:

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

+0

“override”关键字通过让编译器检查函数是否实际覆盖任何基本方法来帮助消除人为错误(如错别字)。至于这个问题,我知道这一点。有没有什么办法可以使它们协变而不使用指针或引用? – Zeenobit

+0

所以我想没有解决方案来完成这项工作。谢谢,人们。我会尝试使用不同的层次结构。 – Zeenobit

0

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

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

另一种解决方案,而不是返回一个值,你的函数可以采取的指针或引用的水果,它则可以填写。

另一种解决方案是有某种容器对象在内部将举行苹果或橙色。这样你可以返回它。

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作为模板参数的类模板,或者你可能需要完全摆脱继承。

0

报告的错误告诉你所有你需要的。这意味着在Derived方法中返回的类型需要从基方法返回的类型派生。

这是如此,如果基本方法被虚拟调用,返回的对象可以被看作是由base方法返回的。

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

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

然后有func()返回Fruit*

这会让你面对在某个时刻确定Fruit*delete'd的问题。

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