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
相关产品推荐
相关产品推荐

