c++ - 在虚函数中使用子类类型参数

标签 c++ inheritance polymorphism

我有这段代码(根据我现实生活中的麻烦设计的)

无法编译,提示 ExtendsB 没有实现 B::Run(A* a)。但是,理解 A* Run();

的扩展没有问题
class A { };

class ExtendsA : public A { };

class B
{
public:
    virtual ~B(){}  
    virtual void Run(A* a) = 0;
    virtual A* Run() = 0;
};

class ExtendsB : public B
{
public:
    virtual ~ExtendsB(){}

    // Not OK! It does not see it as an implementation of 
    // virtual void Run(A* a) = 0;
    virtual void Run(ExtendsA* ea) {}; 
    virtual ExtendsA* Run() { return new ExtendsA(); }; // OK
};

为什么 C++ 允许将返回类型更改为子类,但不允许更改参数类型?

这是一个很好的理由还是只是语言规范中的一个遗漏点?

最佳答案

Why C++ allows to change the return type to a sub-class, but not the parameter type?

C++ 标准允许您使用 Covariant return type 虽然覆盖了虚函数,但不允许你修改函数参数。是的,它背后有一个很好的理由。

Rationale:

重写本质上意味着在运行时将调用基类方法或派生类方法,具体取决于指针所指向的实际对象。
这意味着:
即:“可以调用基类方法的每个实例都可以通过调用派生类方法来替换,而无需更改调用代码。”

如果没有上述规则,它会留下一个窗口,通过添加新功能(新的派生类)来破坏现有代码。

如果派生类中的函数原型(prototype)与基类虚函数 w.r.t 参数不同,则该函数不会覆盖基类函数,因为上述规则已被破坏。

但是,协变返回类型不会违反此规则,因为向上转换是隐式发生的,并且基类指针始终可以指向派生类对象而无需任何转换,因此标准对返回类型强制执行协变返回类型的这一条件。

关于c++ - 在虚函数中使用子类类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12369206/

相关文章:

c++ - 如何为一组对重载比较运算符?

javascript - 基于原型(prototype)与基于类的继承

c# - 如果一个类正在使用一个接口(interface),它必须

class - Lua 中的继承是基于原型(prototype)的还是基于类的?

c# - new() 约束对类定义有何作用?

具有接口(interface)成员变量和成员方法的 Java 类的行为不同。请解释

c++ - 如何在C++中重新声明类对象?

C++反射是如何实现的

c++ - 丢弃/忽略一行的其余部分形成 C++ 中的文件

C++ 构造函数成员初始化列表,对象切片