具有重写函数的继承 我在看一些C++示例代码,它有效地有以下内容: class Foo : public mynamespace::Bar { public: Foo() { // Do some stuff } void Delta() override { // Do some stuff Bar::Delta(); } };

具有重写函数的继承 我在看一些C++示例代码,它有效地有以下内容: class Foo : public mynamespace::Bar { public: Foo() { // Do some stuff } void Delta() override { // Do some stuff Bar::Delta(); } };,c++,C++,我很难理解为什么行Bar::Delta()存在。假定类Foo继承类Bar,那么当调用Foo::Delta()时,肯定会覆盖Bar::Delta()中存在的任何内容,因此此行是多余的 还是我误解了整个继承权的事情?也许override不会覆盖所有内容 Bar::Delta(); 是一个函数调用。这不就是它看起来的样子吗 它调用的是Delta的基类版本,除了Foo版本所做的任何额外工作之外,它还显式地将其限定为Bar::Delta 也许覆盖并不能覆盖一切 Bar::Delta(); overr

我很难理解为什么行
Bar::Delta()存在。假定类
Foo
继承类
Bar
,那么当调用
Foo::Delta()
时,肯定会覆盖
Bar::Delta()
中存在的任何内容,因此此行是多余的

还是我误解了整个继承权的事情?也许
override
不会覆盖所有内容

Bar::Delta();
是一个函数调用。这不就是它看起来的样子吗

它调用的是
Delta
的基类版本,除了Foo
版本所做的任何额外工作之外,它还显式地将其限定为
Bar::Delta


也许覆盖并不能覆盖一切

Bar::Delta();
override
关键字只要求编译器验证您是否真的重写了一个虚拟函数——否则,很容易意外地编写一个不重写任何内容的新函数(例如,由于参数类型略有不同,或者某个版本是const限定的,或者您更改了基类而忘记更新派生类,或者…)

在这里,您正在重写虚拟函数。这不会阻止基类实现的存在,正如您所看到的,您仍然可以调用它


<>你可以(也应该)测试你自己对这类事情的直觉。考虑下面的琐碎测试代码。你认为它能做什么?

现在实际运行它。你是对的吗?如果不是,哪部分是意外的

#include <iostream>
using namespace std;

struct Bar {
    virtual void Delta() {
        cout << "Bar::Delta\n";
    }
};

struct Foo : public Bar {
    void Delta() override
    {
        cout << "Foo::Delta\n";
        Bar::Delta();
    }
};

int main()
{
    cout << "b.Delta()\n";
    Bar b;
    b.Delta();

    cout << "f.Delta()\n";
    Foo f;
    f.Delta();

    cout << "pb->Delta()\n";
    Bar *pb = &b;
    pb->Delta();

    cout << "pb->Delta()\n";
    pb = &f;
    pb->Delta();
}
#包括
使用名称空间std;
结构条{
虚空增量(){
库特
也许覆盖并不能覆盖一切

Bar::Delta();
重写说明符可用于在重写函数时进行编译时检查,以确定被重写的函数是虚拟的且实际上正在被重写

线条栏::Delta();存在的原因

此行调用base
Delta
函数,该函数可能有一些有用的任务要执行,即使您已经覆盖了它

一个简单的例子:

class Base
{
public:
    virtual ~Base() {}
    virtual void Foo()
    {
        // run tasks that are common to all derived types
    }
};

class Derived : public Base
{
public:
    void Foo() override
    {
        Base::Foo(); // we have to call this explicitly
        // run tasks specific to the derived type
    }
};

这是一种常见的模式。事实上,调用重写成员函数的
语法专门针对这种情况

基类中的成员函数执行一些可以独立于派生类执行的计算或操作,并让派生类执行特定于派生的操作,这是非常常见的

下面是一个虚构的例子:

class Stock {
protected:
    double totalDividend;
    double baseDividend;
    double adjustmentFactor;
public:
    Stock(double d, double a)
    : baseDividend(d), totalDividend(d), adjustmentFactor(a) {
    }
    virtual void double ComputeDividend() {
        return totalDividend * adjustmentFactor;
    }
};

class SpecialStock {
private:
    double specialDividend;
public:
    SpecialStock(double d, double sd, double a)
    : Stock(d, a), specialDividend(sd) {
    }
    virtual void double ComputeDividend() override {
        // Do some preparations
        totalDividend = baseDividend + specialDividend;
        // Call the overridden function from the base class
        return Stock::ComputeDividend();
    }
};

您似乎误解了
override
c++
中的含义。对于您的情况,您不应该为它操心。它就像一个普通的虚拟函数。
override
关键字只是一种确保基类具有匹配函数的安全机制。除了语义编译时检查之外,它不会更改任何内容

防范典型的不匹配有些有用,例如
const
与非
const
版本等


虚拟方法机制不会替换原始成员函数。它仍然存在于
派生的
对象中。实际情况是引入了一个间接级别,因此对
base.foo()
的调用使用函数指针来调用正确的实现,即
派生的::foo()
在你的例子中。但是
Base::Foo()
仍然存在,这是“访问”它的语法。你可以通过搜索
virtual
方法上的资料来查看它到底是如何工作的。

Foo中的Delta是一个虚拟方法,它“做一些事情”,然后调用基类的Delta实现


override不会重写任何内容,将方法声明为虚拟方法会执行此操作。override只是让编译器在父类没有Delta方法的情况下抛出语法错误。

有时基类有一些有用的任务要执行,而不管是否被重写。
Bar::Delta()
调用
Bar::Delta
-此函数仍然存在,
覆盖
只是为了确保实际存在具有相同签名的
虚拟
函数-如果没有,将导致编译错误。