You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++嵌套多态疑问:基类含虚函数,派生类无虚函数为何仍生效?

问题解答:派生类未显式声明虚函数时的多态生效问题

首先来看你提供的代码:

#include <iostream>
class base {
public:
    virtual void print(){ std::cout << "base\n"; }
};
class dr : public base {
public:
    void print(){ std::cout << "dr\n"; }
};
class last : public dr {
public:
    void print(){ std::cout << "last\n"; }
};
int main(){
    dr *d = new last();
    d->print();
    return 0;
}

你的观察完全正确——这段代码输出last,说明多态确实生效了。核心结论是:只要继承链中某个基类已经将函数声明为virtual,那么所有派生类中重写该函数的版本会自动成为虚函数,即便派生类没有显式添加virtual关键字,多态依然能正常工作。

具体原因分析:

  • 在C++的继承规则里,虚函数的“虚属性”是会沿继承链传递的。当基类base把print()声明为virtual后,任何派生类(比如dr、last)中,只要函数签名(返回值、函数名、参数列表)和基类的虚函数完全匹配,这个函数就自动成为虚函数,不需要再显式写virtual。
  • 你代码中的dr::print()虽然没写virtual,但它本质上是重写了base的虚函数,因此它自己也变成了虚函数;同理last::print()重写的是dr的虚函数,自然也是虚函数。
  • 当通过dr*指针调用print()时,编译器会触发动态绑定,根据指针实际指向的对象类型(last)来调用对应的函数版本,所以输出last而不是dr。

额外建议:

虽然编译器会自动处理虚属性的传递,但从C++11开始,推荐在派生类的重写函数前添加override关键字,比如:

class dr : public base {
public:
    void print() override { std::cout << "dr\n"; }
};

这样做的好处是:如果你的函数签名和基类的虚函数不匹配(比如参数写错),编译器会直接报错,避免因为意外的函数隐藏而导致多态失效,让代码的意图更清晰。

内容的提问来源于stack exchange,提问作者Dan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:32:33