C++虚函数在基类中不实现导致的报错

本文探讨了C++中虚函数表的概念,并通过一个具体的案例分析了如何解决因虚函数未正确实现导致的运行时错误。文章强调了虚函数在基类与派生类中的实现细节,以及如何通过纯虚函数来避免此类问题。

今天遇到了一个BUG,出错如下图1所示,是什么matrix()函数未定义,引用自某类A(图1中PinholeCamera类)所在文件中的vtable。
我搜了一下整个A所在的文件也没有找到vtable和有关matrix()函数的调用,感到莫名其妙。
后来去看了一下A的基类B(也就是图1中AbstractCamera类),找到一个虚函数matrix(),将其注释后BUG消除。
原来vtable指的是虚函数表。

经过反思和VS中的试验,得出结论如下:
1. 虚函数在派生类中可不实现(常识),但是在基类中必须实现,哪怕在派生类中实现也不行(图2),除非:
2. 设置为纯虚函数(图3)
3. 就算只实例化,而不使用该函数也不行(图4、5)
4. 不实例化该基类倒是可以的(图6)

图1:
这里写图片描述

图2:
这里写图片描述

图3:
这里写图片描述

图4、5:
这里写图片描述
这里写图片描述

图6:
这里写图片描述

<think>好的,用户的问题是“C++基类虚函数是否必须有函数体”。我需要详细回答这个问题,首先回忆C++的相关规则。 首先,虚函数的定义。在C++中,虚函数用于实现多态,基类声明虚函数,派生类可以覆盖它。那么基类虚函数是否必须有函数体? 如果是纯虚函数的话,基类需要定义函数体,只需要声明并赋值为0,这样基类成为抽象类,能实例化。例如:virtual void func() = 0; 这种情况下,基类虚函数(纯虚函数)没有函数体。 如果是普通的虚函数(非纯虚),那么基类必须提供函数体,否则会导致链接错误。因为当派生类没有覆盖该虚函数时,调用该函数会使用基类实现,所以基类必须有定义。例如:virtual void func() { /* 实现 */ } 这里基类必须有函数体。 需要区分纯虚函数和普通虚函数。纯虚函数可以没有函数体,但基类因此成为抽象类。普通虚函数必须有函数体,否则链接失败。 另外,C++11引入了override和final关键字,但这影响虚函数是否需要函数体的规则。 可能用户会混淆纯虚函数和普通虚函数的情况,所以需要明确这两种情况的区别。 总结:基类虚函数如果是纯虚的(=0),则需要函数体;如果是普通虚函数(非纯虚),则必须有函数体,否则链接错误。 </think> 在C++中,基类虚函数是否需要函数体,需根据其是否为**纯虚函数**来区分: ### 一、纯虚函数(Pure Virtual Function) 若虚函数声明时被赋值为 `=0`(即纯虚函数),则**基类中可以提供函数体**(但允许提供,C++标准支持纯虚函数实现)。此时基类成为**抽象类**(Abstract Class),无法直接实例化,必须由派生类覆盖该纯虚函数并提供具体实现后,派生类才能实例化。 示例: ```cpp class Base { public: virtual void pure_virtual_func() = 0; // 纯虚函数,无函数体(合法) }; // 派生类必须实现虚函数才能实例化 class Derived : public Base { public: void pure_virtual_func() override { // 派生类实现 } }; ``` ### 二、普通虚函数(Non-Pure Virtual Function) 若虚函数未被声明为纯虚函数(即未赋值为 `=0`),则**基类中必须提供函数体**。否则编译器在链接阶段会报错(如“undefined reference to `Base::virtual_func()`”)。 这是因为当派生类未覆盖该虚函数时,调用该函数会使用基类的默认实现,因此基类必须提供具体实现。 示例: ```cpp class Base { public: virtual void normal_virtual_func() { // 普通虚函数,必须有函数体 // 基类默认实现 } }; class Derived : public Base { // 未覆盖normal_virtual_func,调用时使用基类实现 }; ``` ### 特殊说明 C++标准允许为纯虚函数提供函数体(但需在类外定义),此时派生类仍需覆盖该函数才能实例化,但基类的纯虚函数实现可通过 `Base::pure_virtual_func()` 显式调用(如派生类在覆盖时调用基类版本)。 示例: ```cpp class Base { public: virtual void pure_virtual_func() = 0; // 声明为纯虚 }; // 类外提供纯虚函数实现(合法但非必须) void Base::pure_virtual_func() { // 基类实现(如公共逻辑) } class Derived : public Base { public: void pure_virtual_func() override { Base::pure_virtual_func(); // 调用基类虚函数实现 // 派生类扩展逻辑 } }; ``` 综上,基类虚函数是否需要函数体的核心规则是:**纯虚函数无需(但允许)提供函数体,普通虚函数必须提供函数体**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值