news 2026/9/29 15:08:01

派生类重写基类虚函数,需要有定义,否则报错undefined reference to vtable for Derived

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
派生类重写基类虚函数,需要有定义,否则报错undefined reference to vtable for Derived

一、源代码

#include<iostream>// /*structBase{virtualvoidf(){}};structDerived:Base{voidf()override;};intmain(){Base*p=new Derived;return0;}// *//* #include <memory> struct Base { virtual void f() {} //virtual ~Base() = default; }; struct Derived : Base { void f() override {} }; int main() { std::unique_ptr<Base> p = std::make_unique<Derived>(); p->f(); std::cout << " Derived class object is created and function f() is called." << std::endl; } */

二、报错信息

g++ polymorph.cpp /usr/bin/ld: /tmp/ccLc7YZm.o: warning: relocation against`_ZTV7Derived'inread-only section`.text._ZN7DerivedC2Ev[_ZN7DerivedC5Ev]' /usr/bin/ld: /tmp/ccLc7YZm.o: in function `Derived::Derived()':polymorph.cpp:(.text._ZN7DerivedC2Ev[_ZN7DerivedC5Ev]+0x1f): undefined reference to `vtableforDerived' /usr/bin/ld: warning: creating DT_TEXTRELina PIE collect2: error: ld returned1exitstatus

三、解析

问题在第 9 行:Derived::f()只有声明,没有定义
structDerived:Base{voidf()override;// 只声明,没有函数体};

为什么报的是"undefined reference to vtable for Derived"?

原因分析

  1. 有虚函数的类都需要一张虚函数表(vtable)
    构造Derived对象时,构造函数要把vptr指向vtable for Derived(链接错误里的_ZTV7Derived)。所以new Derived会让Derived::Derived()引用这张表。

  2. vtable 生成在哪个 .o 文件里?
    GCC/Clang 遵循 Itanium C++ ABI 的key function(关键函数)规则:类中第一个非内联、非纯虚的虚函数就是 key function。vtable只在定义了 key function 的那个编译单元里生成。

    • Derived的 key function 是f(),因为它是在类外定义(不是 inline)的。
    • 但你从来没有定义f(),所以没有任何编译单元生成 vtable for Derived。
  3. 所以链接器找不到 vtable,就报了这个错
    报错里写的是缺 vtable,而不是缺Derived::f(),因为你的代码里没有直接调用f()。真正缺失的符号是 vtable,缺f()的定义才是根本原因。

另外两条 warning:relocation ... DT_TEXTREL in a PIE也是这个未解析符号带出来的,不用单独处理。

修复方法(选一种)

方法 1:在类内给出定义

structDerived:Base{voidf()override{}};

方法 2:在类外定义(通常写在 .cpp 里)

voidDerived::f(){}

方法 3:确实不需要重写,就删掉这行声明

顺带提一句

Base没有虚析构函数。如果以后执行delete p;(p是Base*,实际指向Derived),行为是未定义的。建议加上:

virtual~Base()=default;

源代码文件下半部分注释里那一版(第 24 行)已经写了这一行,取消注释就行。当前代码没有delete,所以还有一个内存泄漏。改用下面那版的std::unique_ptr可以同时避免这个问题。


Recap:The goal is to getpolymorph.cppto link.
It fails becauseDerived::f()is declared but never defined,
so the vtable forDerivedis never generated. Next,
add a body (void f() override {}) and recompile.

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 15:07:24

基于STM32的智能鸽子驯养系统:从环境监测到自动饲喂的完整设计

1. 从鸽棚里的真实痛点说起&#xff1a;这套系统到底要解决什么养鸽子这件事&#xff0c;外行看是闲情逸致&#xff0c;内行才知道是个精细活。我接触过不少鸽友&#xff0c;有养信鸽参赛的&#xff0c;有做观赏鸽繁育的&#xff0c;也有规模化肉鸽养殖的。聊下来发现一个共性痛…

作者头像 李华
网站建设 2026/9/29 15:06:56

OpenHarmony上Flutter功能卡片组件实战:状态管理与平台通道

最近我一直在折腾 Flutter for OpenHarmony 这套链路&#xff0c;手里的项目是一个文件转换助手 App。整个界面没有用传统的列表页加详情页那种结构&#xff0c;而是把所有操作单元都做成了“功能卡片组件”&#xff1a;选文件是一张卡片、选转换格式是一张卡片、调参数是一张卡…

作者头像 李华
网站建设 2026/9/29 15:06:43

《AI 时代 FPGA 的全栈开发实战·从入门到精通》筑基篇|第3课时

课时导读 前两课时我们完成了两件事:建立了硬件思维(第1课时)、补齐了数字电路地基(第2课时)。本课时回答一个非常实际的问题:2026年,FPGA开发者到底有哪些AI工具可以用?它们各自擅长什么?我应该怎么选、怎么搭配? 很多学习者现在的状态是网上说什么火就用什么:刷…

作者头像 李华
网站建设 2026/9/29 15:06:21

千万级设备并发接入,FluxMQ 如何扛住海量终端连接洪峰?

千万级设备并发接入&#xff0c;FluxMQ 如何扛住海量终端连接洪峰&#xff1f;很多企业都会遇到一个共性问题&#xff1a;平台平时运行稳定&#xff0c;一旦遇到设备批量上线、网络断联回复、整点集中上报&#xff0c;就会出现延迟飙升、设备频繁掉线、系统负载爆表&#xff0c…

作者头像 李华
网站建设 2026/9/29 15:06:05

Linux如何开放SSH服务监听多个端口

Linux上默认SSH服务端口为22&#xff0c;但是通常在一些公司里面这个端口是禁用的&#xff0c;需要进行对应的修改。如果大家要开放多个端口的监听&#xff0c;可以通过如下方法进行配置。首先&#xff0c;修改sshd的配置文件 &#xff0c;默认位置为&#xff1a;/etc/ssh/sshd…

作者头像 李华
网站建设 2026/9/29 15:02:58

普通人也能轻松掌握的20个DeepSeek高频提示词(2025版)

以下这些高频提示词都是普通人很容易就掌握得住的, 总共有20个, 版本是2025版的, 它们把内容覆盖在了六大场景之下, 具体包括基础原则这个方面、职场效率这个方面、内容创作这个方面、编程开发这个方面、学习研究这个方面以及高阶技巧这个方面, 这样做的目的是为了能够帮助大家…

作者头像 李华