重写的函数不会反映在基 class 中,这是正常行为吗?

Overridden function does not reflect in the base class, is this a normal behavior?

给定以下代码:

class Base {
public:
    virtual void Test() {
        cout << "Not Overridden" << endl;
    }
};

class Derived : public Base {
public:
    void Test() override {
        cout << "Overridden" << endl;
    }
};

int main() {
    Base o = Derived();
    o.Test();
    return 0;
}

像我这样来自 Java 背景的人希望编译器输出 Overridden 但令人惊讶的是输出恰恰相反。

如果这是正常行为,那么 C++ 中的继承有什么意义?

我缺少什么?

是的,这是正常行为,多态性仅适用于指针和引用。

使用原始指针:

int main() {
    Base* o = new Derived();
    o->Test();
    delete o; //when done with using it delete it from memory
    //...
}

此内存管理的替代方法是使用 smart pointers.

使用智能指针:

int main() {
    unique_ptr<Base> o(new Derived); // automatic memory management
    o->Test();
    //...
}

参考:

int main() {
    Derived d;
    Base& o = d;
    o.Test();
    //...
}

这是你需要注意的事情,当声明 Derived 对象的块超出范围时,引用将变得无用,例如,如果你 return 它来自函数。

输出:

Overridden

网站上的一些帖子解释了为什么会这样,例如 this one

你的方式导致 object slicing

您还需要添加一个 virtual destructor 到您的基础 class。

Base o = Derived();

o 以上是一个 对象 – 一个 Base 对象 – 而不是 Derived一。 o 对象是通过 object slicingDerived 对象创建的,但 o 仍然是 Base 对象。这里没有动态调度,所以 o.Test() 导致 Base::Test() 被调用。

相反,如果您将 o 声明为指向您创建的 Derived 对象的 Base 指针:

Base* o = new Derived();
o->Test();

在这种情况下,o 是指向对象的 指针 – 而不是对象 – 并且动态调度生效:即使 o是指向 Base 对象的指针,它绑定到 Derived 对象,因此 o->Test() 由于动态调度导致 Derived::Test() 这次被调用。

类似地,如果 o 是对 Base 的引用而不是指针。