覆盖返回基本类型的函数

我有两节课 . 基类 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; 但我最终得到的错误是它没有覆盖基类成员 .

回答(4)

2 years ago

如果C具有完全协方差和逆变支持,则输入中的正确关系为 contravariant ,输出中为 covariant . 即:

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 variant,则会破坏类型系统 . 考虑类似的事情;

Animal* a = new Dog;
a->OverrideMe(new Cat);

如果允许 Dog::OverrideMe 采用 Dog* ,则会失败 - Cat* 不是 Dog* !因此,允许采用 Animal* ......或更通用的东西(例如 Organism* ),因为所有这些都可以正常工作 .

C确实 not 支持输入中的逆变,输出中只有 covariance . 所以你可以写:

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

要么:

Animal* OverrideMe(Animal* ) override { .... }

但没有别的 .

2 years ago

函数参数的类型和函数的cv限定符必须相同 . 所以你可以使用

Child* OverrideMe(Parent* func) override;

2 years ago

您没有覆盖此处,因为您的 OverrideMe 函数不会接受与您尝试覆盖的基类中的函数相同的参数:

class Parent
{
    public:
        virtual Parent* OverrideMe(Parent* func) = 0;
};

class Child : public Parent
{
    public:
        virtual Child* OverrideMe(Parent* func) override;
};

2 years ago

这种“闻起来很糟糕”,换句话说,你正在“破坏”正常的“任何对象都应该可以替换为任何其他对象” .

如果在基类中有接口函数,则该函数应在整个类层次结构中采用相同的类型 .

所以正确的是:

父* OverrideMe(Parent * func)覆盖;

(正如juanchopanza所说,你可以返回一个派生类型,但你确定父返回的值总是同一个类吗?对我来说,这看起来像是可能返回“任何派生对象”的函数类型,在哪种情况下,你要么撒谎,要么以“有趣的效果”结束

如果出于某种原因,在你的情况下这实际上并不“有效”,那么你可能不应该以这种方式使用继承 .