C++ 重写返回基类型的函数
我有两节课。基类C++ 重写返回基类型的函数,c++,inheritance,interface,abstract-class,pure-virtual,C++,Inheritance,Interface,Abstract Class,Pure Virtual,我有两节课。基类父类和派生类子类。类Parent具有返回其类类型的纯虚函数。如何在派生类中重写它 class Parent { public: virtual Parent* OverrideMe(Parent* func) = 0; }; class Child : public Parent { public: Child* OverrideMe(Child* func) override; }; 我尝试了Child*override(Ch
父类
和派生类子类
。类Parent
具有返回其类类型的纯虚函数。如何在派生类中重写它
class Parent
{
public:
virtual Parent* OverrideMe(Parent* func) = 0;
};
class Child : public Parent
{
public:
Child* OverrideMe(Child* func) override;
};
我尝试了
Child*override(Child*func)override代码>,但我最终的错误是它没有覆盖基类成员。函数参数的类型和函数的cv限定符必须相同。所以你可以用
Child* OverrideMe(Parent* func) override;
您没有在此处重写,因为您的OverrideMe
函数与您尝试重写的基类中的函数没有采用相同的参数:
class Parent
{
public:
virtual Parent* OverrideMe(Parent* func) = 0;
};
class Child : public Parent
{
public:
virtual Child* OverrideMe(Parent* func) override;
};
这种“气味难闻”,换言之,你正在“打破”正常的“任何对象都应该可以替换为从它派生的任何其他对象”
如果基类中有接口函数,则该函数在整个类层次结构中应采用相同的类型
因此,正确的做法是:
父项*覆盖项(父项*函数)覆盖
(正如juanchopanza所说,您可以返回一个派生类型,但您确定父级返回的值始终是同一个类吗?对我来说,这似乎是一种可能返回“任何派生对象”的函数类型,在这种情况下,您要么撒谎,要么最终得到“有趣的效果”)
如果由于某种原因,这在你的情况下实际上不“工作”,那么你不应该用这种方式继承。
< P>如果C++具有完全协方差和逆变支持,则正确的关系在输入中是<强>反变< /强>,并且在输出中<强>协变< /强>。即:
struct Organism { };
struct Animal : Organism {
virtual Animal* OverrideMe(Animal* ) = 0;
};
struct Dog : Aniaml {
Dog* OverrideMe(Organism* ) override { ... }
↑↑↑ ↑↑↑↑↑↑↑↑
covariant contravariant
};
这似乎有点不直观,但确实有道理。如果你期待一只动物*
,你应该能够处理任何动物*
(其中一只狗*
合格)。相反,如果你正在对一只动物*
做一些手术,你只需要一个可以对一只动物*
进行手术,而对一个生物体*
进行手术就可以了
请注意,如果输入是co变量,则会破坏类型系统。考虑一些类似的事情;p>
Animal* a = new Dog;
a->OverrideMe(new Cat);
如果Dog::OverrideMe
被允许使用Dog*
,则该操作将失败-aCat*
不是Dog*
!所以它可以带一只动物*
。。。或者任何比这更通用的东西(例如,有机体*
),因为所有这些都可以正常工作
C++不支持输入中的逆变,只支持输出中的协方差。所以你可以写:
Dog* OverrideMe(Animal* ) override { ... }
或:
>但没有别的。虽然C++不支持它,但是逆变将需要一个比<代码>父*<代码>更具体的参数,而不是更具体。关键是您可以使用父项
,而不知道子项
。传递不是子级的父级*
将破坏一切。您的设计是错误的。它应该是“虚拟父项*覆盖项(子项*函数)=0;(带着一个向前的孩子)。尽管如此,这是丑陋的。您可以使父节点和子节点从某个节点派生(避免从父节点到子节点的继承)。
Animal* OverrideMe(Animal* ) override { .... }