C++子类重写基类方法后如何正确调用子类版本方法
问题根源
你当前代码无法触发子类重写方法,是踩了C++多态实现的两个核心规则:
- 基类需要被子类重写的方法没有加
virtual关键字:C++默认对成员方法做静态绑定,编译阶段就根据参数/变量的声明类型确定调用的方法版本,不会在运行时判断对象的实际类型。 call_method使用值传递接收BaseClass类型参数:传入子类对象时会发生对象切片,子类独有的成员和虚表指针部分会被截断,函数内拿到的是纯BaseClass实例,自然只能调用基类版本的方法。
修复步骤
- 给基类中需要被重写的
myMethod加上virtual关键字,开启运行时动态分派;C++11及之后版本建议在子类重写的方法后加override关键字,让编译器帮你检查重写的函数签名是否和基类一致,避免手误写错。 - 多态基类必须把析构函数也声明为
virtual,否则通过基类指针/引用释放子类对象时会触发未定义行为。 - 把
call_method的参数改成基类的引用或者指针,避免值传递导致的对象切片。
修复后的可运行代码:
#include <iostream> using namespace std; //基类 class BaseClass { public: virtual void myMethod(){ std::cout << "Base class?" << std::endl; } // 多态基类必须声明虚析构函数 virtual ~BaseClass() = default; }; //子类 class SubClass1: public BaseClass{ public: // override关键字用于编译期校验重写正确性 void myMethod() override { std::cout << "Subclass?" << std::endl; } }; // 通用调用函数,传基类引用避免切片 void call_method(BaseClass& object){ object.myMethod(); } int main() { BaseClass bc; SubClass1 sb1; // 直接调用子类方法,输出"Subclass?" sb1.myMethod(); // 传入通用函数,现在也会输出"Subclass?" call_method(sb1); return 0; }
其他可选实现
如果不需要强制所有传入类型继承自同一个基类,可以用模板实现编译期多态,没有虚函数的运行时开销,只要传入的类型实现了myMethod方法即可正常调用:
template<typename T> void call_method(T& object){ object.myMethod(); }
这种写法不需要修改基类代码,也支持任意符合接口要求的类型传入,灵活性更高。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

