Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 重写返回基类型的函数_C++_Inheritance_Interface_Abstract Class_Pure Virtual - Fatal编程技术网

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*
,则该操作将失败-a
Cat*
不是
Dog*
!所以它可以带一只
动物*
。。。或者任何比这更通用的东西(例如,
有机体*
),因为所有这些都可以正常工作

C++不支持输入中的逆变,只支持输出中的协方差。所以你可以写:

Dog* OverrideMe(Animal* ) override { ... }
或:


但没有别的。

虽然C++不支持它,但是逆变将需要一个比<代码>父*<代码>更具体的参数,而不是更具体。关键是您可以使用
父项
,而不知道
子项
。传递不是子级的父级*
将破坏一切。您的设计是错误的。它应该是“虚拟父项*覆盖项(子项*函数)=0;(带着一个向前的孩子)。尽管如此,这是丑陋的。您可以使父节点和子节点从某个节点派生(避免从父节点到子节点的继承)。
Animal* OverrideMe(Animal* ) override { .... }