首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

GNU编译器警告"类具有虚函数但非虚析构函数"

这个警告是由GNU编译器生成的,表示在类中定义了虚函数,但是没有声明虚析构函数。这可能会导致潜在的问题,例如当对象被销毁时,虚函数表可能不会被正确地更新。为了解决这个问题,可以在类的析构函数前加上virtual关键字,将其声明为虚析构函数。

例如:

代码语言:txt
复制
class MyClass {
public:
    virtual ~MyClass() {}
    // 其他代码
};

这样,编译器就不会再生成这个警告了。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

【C++】多态 ⑤ ( 函数 | 函数语法 | 函数意义 | 父指针指向子类对象情况下父和子类使用 virtual 函数 | 代码示例 )

; 自身定义的 函数 ; 然后 , 调用 成员 函数 ; 也就是 成员变量 类型的 函数 ; 最后 , 调用 父 函数 ; 2、函数可以是函数 函数 可以是 函数 ; 函数...; 释放 A 类型的指针 , 需要调用其子类 B 类型对象的 函数 , 此时需要将 A 类型 和 B 类型的 函数 声明为 函数 ; 3、函数语法 函数 的 语法 是 在 父...~Base() {} }; 4、函数意义 父中使用了 函数 , 在 子类 中 , 必须 覆盖 父函数 , 并且使用相同的函数签名 ; 如果 子类 没有提供自己的 函数..., 则编译器会自动生成一个 函数 , 该 函数 会首先调用 父函数 , 然后执行 子类 的 函数 ; 使用 函数 的目的是 确保在释放 子类 对象时正确地释放资源和调用函数..., 只有在 父函数函数 时 , 子类 的函数才必须是函数 ; 如果 父函数 不是 函数 , 则 子类 的 函数 可以是 普通的 非虚函数 ; 二、代码示例 -

47420

抽象函数

函数仅适用于有继承关系的对象,所以普通函数不能声明为函数。 2、静态成员函数不能是函数静态成员函数不受对象的捆绑,只有的信息。 3、内联函数不能是函数。...4、构造函数不能是函数,构造时,对象的创建尚未完成。构造完成后,能算一个名符其实的对象。 5、函数可以是函数且通常声明为函数。...(2, 4, 8); s->draw(); // delete 指针,调用函数 delete s; return 0; } 以上代码演示了纯函数的定义,上面代码存在一个问题,我们先看一下运行的结果...,初始化为 0,提供族类的公共接口 virtual void draw() = 0; // 增加 virtual 关键字,让其自动执行子类函数 virtual ~Shape() { cout <...< “Shape destructor” << endl; } protected: int _x; int _y; }; 这样修改代码后,我们再次运行,结果就能看到,Circle 正常被了。

17330

C++核心准则C.127:包含函数应该有函数或保护函数

C.127: A class with a virtual function should have a virtual or protected destructor C.127:包含函数应该有函数或保护函数‍...包含函数通常(大多数情况下)通过指向基的指针使用。通常,最后一个使用者必须通过指向基的指针调用delete操作,通常是指向基的智能指针,因此函数应该是公开的函数。...稍微特殊一些的情况是:如果不希望支持通过指向基的指针销毁对象,函数应该是保护的非虚函数。参见C.35。...包含函数函数要么是公开的函数,要么是保护的非虚函数。...提示针对包含函数却没有函数的销毁操作。

75120

C++核心准则C.35:基函数要么是公开的函数,要么是保护的非虚函数

如果函数是公有的,那么调用侧的代码就会尝试使用基指针销毁派生的对象,在基函数非虚函数时其结果时没有定义的。...如果函数时保护的,那么调用侧代码就无法通过基类型指针销毁派生对象,这是函数就没有必要一定是函数函数是保护而不是私有的,这样派生函数才能调用它。...通常,基的设计者不会知道在函数中应该执行什么样的动作。...我们可以想象一种需要保护的函数函数的情况:当希望允许派生的对象(只有这个类型)通过基指针销毁另外一个对象(不是它自己)时。但是我们还没有在实际的开发中遇到这种情况。...拥有函数函数要么是公开的函数,要么是保护的非虚函数。 译者注:拥有函数一般就意味着它有派生

1K20

从零开始学C++之函数与多态(二):纯函数、抽象函数

Shape是抽象,Draw函数是纯函数,Circle, Square, Rectangle都重新实现了Draw,在这里把Shape的函数声明为函数,那么delete 基指针,会调用派生函数...,并能管理该对象 可以添加新(已有的派生)的新对象,并能管理该对象 四、函数 函数可以声明为函数 delete 基指针; 程序会根据基指针指向的对象的类型确定要调用的函数...基函数函数,所有派生函数都是函数 构造函数不得是函数 如果要操作具有继承关系的的动态对象,最好使用函数。...特别是在派生函数需要完成一些有意义的操作,比如释放内存 函数还可以是纯的。...    Derived d;     return 0; } // 对于一个没有任何接口的,如果想要将它定义成抽象,只能将函数声明为纯的 // 通常情况下在基中纯函数不需要实现 // 例外是纯函数要给出实现

1.3K00

C++编程经验(2):为函数的必要性

这个要提一下,如果记不住就记住:如果不做函数,会有内存泄漏 解释 定义一个基的指针p,在delete p时,如果基函数函数,这时只会看p所赋值的对象,如果p赋值的对象是派生的对象,...就会调用派生函数;如果p赋值的对象是基的对象,就会调用基函数,这样就不会造成内存泄露。...如果基函数不是函数,在delete p时,调用函数时,只会看指针的数据类型,而不会去看赋值的对象,这样就会造成内存泄露。 多少学点设计模式就清楚了。...Inherit :public Base{ //此处省去,一切从简 }; //重点看调用 int main() { Base *p = new Inherit; //这种方式的调用,这时候有没有就不一样了

56210

《Effective C++》读书笔记(2):构造赋值运算

款5、了解C++默认编写并调用哪些函数 通常情况下,如果代码中没有声明构造函数、拷贝构造函数、拷贝运算符、函数编译器会在需要时创建他们,这往往只能满足编译器的需求,很可能无法满足程序的需求.../函数;生成的函数非虚的,除非基函数。...当这样的一个指向派生的基指针时,如果函数不是函数,则直接调用基函数,那么派生获取的资源未释放,则会造成内存泄漏。...而当函数函数时则先调用对应的派生函数,再调用基函数,资源全部释放。...进入函数后派生部分呈未定义值,对象类型是基,调用的是基函数。 总而言之,在构造函数函数函数的行为有特殊变化;为了避免出错,不要在其过程中使用函数

13930

函数? vptr? 指针偏移?多态数组? delete 基指针 内存泄漏?崩溃?

5、 在继承机制中,构造函数函数具有一种特别机制叫 “层链式调用通知” 《 C++编程思想 》 C++标准规定:基函数必须声明为virtual, 如果你不声明,那么"层链式调用通知"这样的机制是没法构建起来....从而就导致了基函数被调用了,而派生函数没有调用这个问题发生....,这是因为我们将基函数声明为函数的原因,在pI 指向派生首地址的前提下,如果~IRectangle()  是函数,那么会找到实际的函数~Rectangle() 执行,而~Rectangle...如果没有这样做的话,只会输出基函数,这种输出情况通过比对规则2也可以理解,pI 现在虽然指向派生对象首地址,执行pI->~IRectangle() 时 发现不是函数,故直接调用, 假如在派生函数内有释放内存资源的操作...将基函数改成函数,fun() 最好也改成函数,只要有一个函数,基大小就为一个vptr ,此时基和派生大小都是4个字节,p也指向派生的首地址,问题解决,参考规则3。

92500

函数? vptr? 指针偏移?多态数组? delete 基指针 内存泄漏?崩溃?

5、 在继承机制中,构造函数函数具有一种特别机制叫 “层链式调用通知” 《 C++编程思想 》 C++标准规定:基函数必须声明为virtual, 如果你不声明,那么"层链式调用通知"这样的机制是没法构建起来....从而就导致了基函数被调用了,而派生函数没有调用这个问题发生....,这是因为我们将基函数声明为函数的原因,在pI 指向派生首地址的前提下,如果~IRectangle() 是函数,那么会找到实际的函数~Rectangle() 执行,而~Rectangle...如果没有这样做的话,只会输出基函数,这种输出情况通过比对规则2也可以理解,pI 现在虽然指向派生对象首地址,执行pI->~IRectangle() 时 发现不是函数,故直接调用, 假如在派生函数内有释放内存资源的操作...将基函数改成函数,fun() 最好也改成函数,只要有一个函数,基大小就为一个vptr ,此时基和派生大小都是4个字节,p也指向派生的首地址,问题解决,参考规则3。

97520

EasyC++79,函数注意事项

在定义基时,需要将要在派生中重新定义的方法声明为,如函数 除了这些之外,我们还有一些其他需要注意的事项。...一般我们会在派生中调用基的构造函数,这其实不是继承机制,所以将构造函数声明为没有意义。 函数 前文说过函数应该是函数,除非类不被继承。...因为派生当中往往含有独有的成员变量,如果函数非虚,那么会导致在对象时仅调用基函数,从而导致独有的成员变量内存不被释放,引起内存泄漏。...我试了一下,在我的g++编译器当中,会报错: 根据C++ Primer中的说法,在一些古老的编译器当中,可能不会报错,甚至可能连警告都没有。...这可能和编译器版本有关,在新版的编译器当中似乎取消了这一设定。 我尝试了一下,发现并不会隐藏,一样可以顺利调用父方法。

21310

《Effective C++》读书摘要

(二)、构造//赋值运算 五、C++默认编写的函数 默认构造、复制构造、、赋值运算符。 六、拒绝自动生成的函数 私有化拷贝构造和赋值运算符; 私有继承UnCopyable手工。 ?...七、多态基声明函数 (不)具有多态性质基(不)需要函数; 八、不让异常逃出 异常时终止或者吞下; 将可能抛出异常的代码提供给用户管理; 九、不在构造和中调用函数 调用后仅仅是自身的函数...十二、复制对象要面面俱到 不要丢失基的成员的复制。 (三)、资源管理 十三、对象管理资源 构造函数获得资源,函数释放资源; 使用智能指针封装:tr1::shared_ptr和auto_ptr。...三十、inline里里外外 隐式:累内直接定义成(友)员函数,显式:inline关键字; 拒绝:复杂、函数函数指针调用、模板、构造函数、影响动态连接或升级、对调试器的挑战(禁用)。...三十六、绝不定义继承的非虚函数 重修继承的非虚函数导致函数的访问由指向对象的指针或引用类型决定。

1.9K60

《Effective C++》学习笔记

构造//赋值运算 条款05:了解C++默默编写并调用哪些函数 当没有声明时,编译器会自动为创建默认构造函数函数、复制构造函数和赋值构造函数如果成员变量中包含引用、const这些不能被改变的值...条款07:为多态基声明函数 如果一个基可能有多态子类,那么就该声明一个函数。 如果一个有任何函数,那么它就应该有函数。...如果一个不被用来做基,那么就不该声明函数。...条款09:绝不在构造和过程中调用函数 在构造函数函数中不要去调用函数,因为子类在构造/时,会调用父的构造/函数,此时其中的函数是调用父的实现,这是父函数可能是纯函数...杂项讨论 条款53:不要轻忽编译器警告 对于编译器编译时给出的警告信息,最好立即修复,避免后续调试半天来寻找编译器早就告知你的问题。

1.1K20

C++核心准则​讨论:将基函数设为公共和虚拟的,或受保护的和非虚拟的

函数应该是函数吗?也就是说,是否应该允许通过指向基的指针进行销毁?如果是,则base的函数必须是公共的才能被调用,否则虚拟调用它会导致未定义的行为。...否则,应该对其进行保护,以便只有派生才能在自己的函数中调用它,这个函数也应该是非虚的,因为它不需要虚拟地运行。...这种情况导致较早的编码标准对所有基函数都必须是虚拟的提出了全面的要求。这太过分了(即使是常见情况);相反,规则应该是当且仅当基函数是公共的时,才将它们函数化。...可以看作只是另一种操作,尽管具有使非虚调用变得危险或错误的特殊语义。因此,对于基函数,选择是根据是否允许通过指向Base的指针实际上调用它。“非虚”不是一种选择。...推论:编写基时,请始终显式编写一个函数,因为隐式生成的是公共的和非虚的。如果默认函数就很好,那么您只需要决定器可见性和函数性,则实现可以直接使用=default。

1.1K20

Effective_Cpp中的55个建议

class HomeForSale: private Uncopyable{...}; 7:为多态基声明virtual函数 1.带有多态性质的基应该声明一个函数。...如果一个里面有任何函数,那么它也应该有一个函数。 2.如果一个的设计目的不是为了多态,那么就不该声明virtual函数。...8:别让异常逃离析函数 1.函数绝对不要吐出异常,如果一个被函数调用的函数可能抛出异常,函数应该捕捉任何异常,然后吞下它们或结束程序。...9:绝对不要在构造和过程中调用函数 当构造子类的时候,需要先去调用父的构造函数,这时候子类还不存在,是无法去自动调用子类的函数的。...49-52未读 杂项讨论 53:不要轻忽编译器警告 1.严肃对待编译器发出的警告信息。努力在你的编译器的最高警告级别下争取无任何警告

55330

C++:28 --- C++内存布局(上)

6 特殊成员函数 构造函数函数 正如我们所见,在构造和过程中,有时需要初始化一些隐藏的成员变量。...1 * 合成并初始化函数表成员变量 2 * 执行函数体中,程序定义的其他代码 3 * 调用成员变量的函数(按照相反的顺序) 4 * 调用直接非虚函数(按照相反的顺序) 5 * 如果是...“最终派生”,调用函数(按照相反顺序) 在VC++中,有的构造函数接受一个隐藏的“最终派生标志”,标示是否需要初始化。...对于函数,VC++采用“分层析构模型”,代码中加入一个隐藏的函数,该函数被用于包含(对于“最终派生”实例而言);代码中再加入另一个函数不包含。...前一个函数调用后一个。 7 数组 堆上分配空间的数组使函数进一步复杂化。问题变复杂的原因有两个: 1、 堆上分配空间的数组,由于数组可大可小,所以,数组大小值应该和数组一起保存。

1K20

C++primer学习笔记(六)

virtual函数是基希望派生重新定义的函数,希望派生继承的函数不能为函数。根一般要定义函数。 派生只能通过派生对象访问protected成员,不能用基对象访问。...基定义为virtual就一直为函数,派生写不写virtual都是函数。用做基必须是已定义的。 存在函数+指针或引用==产生多态。非虚函数编译时就按指针或引用或对象类型确定。...派生继承基的访问控制标号【何种方式继承】无论是什么,不影响派生使用基成员,影响使用派生的用户访问基成员。使用接口继承还是实现继承对派生用户具有重要含义。 友元关系不继承。...派生函数不负责清除基成员,每个函数只负责清除自己成员。...派生指针的静态类型和动态类型不一致时【基指针指向派生是时】,为保证删除指针调用合适的函数【多态】,基必须为virtual。

1.1K20

1小时深入c++面向对象编程

派生函数 函数不能被继承 执行派生函数时,基函数也将被调用 函数的执行顺序与构造函数严格相反 4.2.9 示例 ?...图4-8 派生构造函数调用顺序 4.2.10 派生构造函数使用中应注意的问题 派生构造函数的定义中可以省略对基构造函数的调用,其条件是在基中必须有缺省的构造函数或者根本没有定义任何构造函数编译器会自动生成缺省构造函数...图4-15 二义性示例 4.4 格式:virtual 说明:关键字virtual与关键字public或private的相对位置无关,必须位于名之前,且virtual...图4-16 非虚存储结构 4.4.2 的构造函数 派生中只有一个子对象 构造函数必须只被调用一次,目的是要保证子对象只被初始化一次 最派生:继承结构中建立对象时所指定的...子对象由最派生的构造函数通过调用的构造函数进行初始化 在一个成员初始化列表中出现对和对非虚构造函数的调用时,的构造函数先于非虚的构造函数的执行 最派生的构造函数的成员初始化列表中必须给出对的构造函数的调用

60720

C++多态实现原理

,BaseClass定义了函数函数VirtualFunction1、函数VirtualFunction2、非虚函数NonVirtualFunction。...然后定义子类SubClass继承于BaseClass,覆盖重写BaseClass的函数函数VirtualFunction1、函数NonVirtualFunction,未覆盖重写BaseClass...但是,subClass覆盖重写了baseClass的函数和VirtualFunction1,所以第一和第二个元素的值不同,指向的是SubClass对应的函数。...可见,调用函数和调用非虚函数有很大区别,调用函数时是在运行时期决定的,而调用非虚函数是在编译时期就决定了。...调用函数时会查询函数表对应函数的地址,如果子类覆盖重写基函数,子类的函数表对应函数的地址就会被编译器更新为子类的函数

52110

C++与汇编小结

函数编译器会为每一个包含函数(或通过继承得到的子类)生成一个表,其中包含指向中每一个函数的指针。 这样的表就叫做表(vtable)。...1、非虚函数 hello()是BaseClass中的非虚成员函数,不需要通过表查找,编译器直接生成调用语句call BaseClass::hello(),并且第一个参数默认为this指针。...堆分配的对象的函数在分配给对象的内存释放之前通过 delete 操作符调用。 其过程如下: 1、如果类拥有任何函数,则还原对象的表指针,使其指向相关表。...4、如果对象拥有一个超,则调用超函数 5、如果是释放堆的对象,则用一个代理函数执行1~4步骤,并在最后调用delete操作符释放堆上的对象。...我们希望当调用C++基BaseClass的函数时能够触发动态绑定,能够找到当前对象所属函数表中的函数

1.2K40

第 15 章 面向对象程序设计

而对于非虚函数的调用是在编译时进行绑定。类似的,通过对象进行的函数函数非虚函数)调用也在编译时绑定。 一旦某个函数被声明为函数,则在所有派生中它都是函数。...函数属性会被继承,无论派生中使用合成的函数还是自定义的函数,都将是函数。这样,就能保证 delete基指针时总能运行正确的函数版本。...假如基函数不是函数,且指针的静态类型与动态类型不一致,则此时只能调用基函数,那派生对象的部分则无法完成,从而产生未定义行为。...如前所述,当一个中存在拷贝控制成员时,编译器不会为这个合成移动操作。对于需要定义函数的基,也是如此。...如果在基中有一个不可访问和删除掉的函数,则派生中合成的默认拷贝构造函数将是删除的,因为编译器无法销毁派生对象的基部分。 和过去一样,编译器将不会隐式合成一个删除掉的移动操作。

1K30
领券