ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

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

派生类重写基类虚函数,需要有定义,否则报错undefined reference to vtable for Derived 一、源代码#includeiostream// /*structBase{virtualvoidf(){}};structDerived:Base{voidf()override;};intmain(){Base*pnew Derived;return0;}// *//* #include memory struct Base { virtual void f() {} //virtual ~Base() default; }; struct Derived : Base { void f() override {} }; int main() { std::unique_ptrBase p std::make_uniqueDerived(); 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_ZTV7Derivedinread-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原因分析有虚函数的类都需要一张虚函数表vtable构造Derived对象时构造函数要把vptr指向vtable for Derived链接错误里的_ZTV7Derived。所以new Derived会让Derived::Derived()引用这张表。vtable 生成在哪个 .o 文件里GCC/Clang 遵循 Itanium C ABI 的key function关键函数规则类中第一个非内联、非纯虚的虚函数就是 key function。vtable只在定义了 key function 的那个编译单元里生成。Derived的 key function 是f()因为它是在类外定义不是 inline的。但你从来没有定义f()所以没有任何编译单元生成 vtable for Derived。所以链接器找不到 vtable就报了这个错报错里写的是缺 vtable而不是缺Derived::f()因为你的代码里没有直接调用f()。真正缺失的符号是 vtable缺f()的定义才是根本原因。另外两条 warningrelocation ... 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可以同时避免这个问题。RecapThe 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.
返回列表