首页 文章

覆盖返回基本类型的函数

提问于
浏览
1

我有两节课 . 基类 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

    如果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 { .... }
    

    但没有别的 .

  • 0

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

    Child* OverrideMe(Parent* func) override;
    
  • 3

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

    class Parent
    {
        public:
            virtual Parent* OverrideMe(Parent* func) = 0;
    };
    
    class Child : public Parent
    {
        public:
            virtual Child* OverrideMe(Parent* func) override;
    };
    
  • 3

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

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

    所以正确的是:

    父* OverrideMe(Parent * func)覆盖;

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

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

相关问题