我有两节课。基类Parent
和派生类Child
。类Parent
具有返回其类类型的纯虚函数。如何在派生类中覆盖它?
class Parent
{
public:
virtual Parent* OverrideMe(Parent* func) = 0;
};
class Child : public Parent
{
public:
Child* OverrideMe(Child* func) override;
};
我尝试了Child* OverrideMe(Child* func) override;
,但我最终错误地认为它没有覆盖基类成员。
答案 0 :(得分:3)
函数参数的类型和函数的cv限定符必须相同。所以你可以使用
Child* OverrideMe(Parent* func) override;
答案 1 :(得分:3)
如果C ++具有完全协方差和逆变支持,则输入中的正确关系逆变,输出中的协变。即:
struct Organism { };
struct Animal : Organism {
virtual Animal* OverrideMe(Animal* ) = 0;
};
struct Dog : Aniaml {
Dog* OverrideMe(Organism* ) override { ... }
↑↑↑ ↑↑↑↑↑↑↑↑
covariant contravariant
};
这似乎有点不直观,但它确实有意义。如果您期望Animal*
,则应该能够处理Animal*
(Dog*
符合条件的任何内容)。相反,如果您在Animal*
上执行某些操作,则只需要一个可以执行Animal*
的操作 - 并且需要Organism*
的操作符合该前端的条件。
请注意,如果输入为 co </ strong>变体,则会破坏类型系统。考虑类似的事情;
Animal* a = new Dog;
a->OverrideMe(new Cat);
如果允许Dog::OverrideMe
使用Dog*
,则会失败 - Cat*
不是Dog*
!因此,允许使用Animal*
...或更通用的内容(例如Organism*
),因为所有这些都可以正常工作。
C ++ 不支持输入中的逆变,输出中只有协方差。所以你可以写:
Dog* OverrideMe(Animal* ) override { ... }
或:
Animal* OverrideMe(Animal* ) override { .... }
但没有别的。
答案 2 :(得分:2)
你没有在这里覆盖,因为你的OverrideMe
函数没有采用与你试图覆盖的基类中的函数相同的参数:
class Parent
{
public:
virtual Parent* OverrideMe(Parent* func) = 0;
};
class Child : public Parent
{
public:
virtual Child* OverrideMe(Parent* func) override;
};
答案 3 :(得分:0)
这“闻起来很糟糕”,换句话说,你正在“破坏”正常的“任何对象都应该可以替换为任何其他对象”。
如果在基类中有接口函数,则该函数应在整个类层次结构中采用相同的类型。
所以正确的事情是:
父* OverrideMe(Parent * func)覆盖;
(正如juanchopanza所说,你可以返回一个派生类型,但你确定父返回的值总是同一个类吗?对我来说,这看起来像是可能返回“任何派生对象的函数类型” “,在这种情况下,你要么撒谎,要么结束”有趣的效果“)
如果出于某种原因,在你的情况下这实际上并不“有效”,那么你可能不应该以这种方式使用继承。