覆盖 return 基本类型的函数

Override function that return base type

我有两个 class。基础 class Parent 和派生 class Child。 Class Parent 具有 returns 其 class 类型的纯虚函数。如何在派生 class?

中覆盖它
class Parent
{
    public:
        virtual Parent* OverrideMe(Parent* func) = 0;
};

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

我尝试了 Child* OverrideMe(Child* func) override; 但我最终遇到错误,它没有覆盖基础 class 成员。

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

Child* OverrideMe(Parent* func) override;

你没有在这里重写,因为你的 OverrideMe 函数没有接受与你试图重写的基础 class 中的函数相同的参数:

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

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

这个"smells bad",也就是说,你是"breaking"正常的"any object should be replaceable with any other object that is derived from it"。

如果您在 base-class 中有一个接口函数,那么该函数在整个 class 层次结构中应该采用相同的类型。

所以正确的做法是:

Parent* OverrideMe(Parent* func)覆盖;

(正如 juanchopanza 所说,您可以 return 派生类型,但您确定父 returned 值将始终相同 class 吗?对我来说,这看起来像是可能 return "any derived object" 的函数类型,在这种情况下,您要么撒谎,要么最终得到 "Interesting effects")

如果出于某种原因,这实际上 "work" 您的情况,那么您可能不应该以这种方式使用继承。

如果 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 变体,那将破坏类型系统。考虑类似的东西;

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

如果允许 Dog::OverrideMe 获得 Dog*,那将失败 - Cat* 不是 Dog*!所以允许使用 Animal* ... 或任何比它更通用的东西(例如 Organism*),因为所有这些都可以正常工作。

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

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

或:

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

但没有别的。