首页 > 编程语言 >Effective C++ 之【条款7:为多态基类声明virtual析构函数】

Effective C++ 之【条款7:为多态基类声明virtual析构函数】

时间:2025-01-15 13:32:59浏览次数:3  
标签:函数 Effective Point 多态 C++ virtual 析构 SpecialString class

文章目录


Tips1

polymorphic(带有多态性质的)base classes应该声明一个virtual的虚构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构函数。

Tips2

Classes的设计目的如果不是作为 base classes 使用,或者不是为了具备多态性(polymorphically),就不该声明virtual析构函数。


一、为什么要有virtual析构函数?

C++明确指出,当derived class对象经由一个base class指针被删除,而base class带有一个non-virtual析构函数,其结果未有定义,实际执行时通常发生的是对象的derived成分没被销毁。

class SpecialString: public std::string
{
	//馊主意!std::string有个non-virtual的析构函数
}

// 错误使用方法
SpecialString *pss = new SpecialString("Bad Action");
std::string *ps;
...
ps = pss;	//SpecialString* => std::string*
...
delete ps;	//未有定义!
//现实中 *ps 的SpecialString资源造成了泄露,因为SpecialString的析构函数未被调用。
//虚表指针觉得这个时候应该调用std::string的析构函数。

二、为什么有时候不要声明虚构函数?

如果你不想让一个类成为基类,那么在类中声明虚函数是是一个坏主意,因为额外存储的虚表指针会使类的体积变大。考虑如下情况:

class Point
{
public:
	Point(int x, int y);	//一个二维空间点
	~Point();
private:
	int x;
	int y;
}

Point对象可以塞入到一个64-bit的缓存器中。如果Point的析构函数是virtual 的话,该对象的体积变大了,因为还需要存放虚表指针vptr(virtual table point)。虚表(vtbl)的占用倒是无关紧要,因为多个Point对象共用一个vtbl。在32-bit计算机体系结构中,Point占用空间大小由64bit(2个int)变成96bit(2个int和1个vptr);在64-bit架构中可能占用64-128bits,因为此时指针占64bits。因此一个virtual虚构函数将会导致对象大小增加50%~100%!
这样Point对象也不能塞入到一个64-bit的缓存器了,C++的Point对象就不能再和其他语言(如C)的相同声明具备一样的结构了,因此也无法传递至其他语言写的函数中去了。

三、使用一下纯虚函数。

虚析构函数的运作方式是,最深层派生的那个类的析构函数最先被调用,然后是其上的基类的析构函数被依次调用。如果你想将基类作为抽象类使用,但似乎没有适合的函数作为虚函数,那么将它的析构函数设为纯虚函数是一个不错的想法。下面是个例子:

class AWOV
{
public:
	virtual ~AWOV() = 0;
}

然后你必须要为纯虚函数析构提供一份定义:

AWOV::~AWOV(){}

Today Thinking~

和技术无关的瞎想

1+1=2吗?这是约定了某种规则吧。
二进制下1+1=10。
1个苹果+1个苹果=2个苹果?
如果按照重量规定,100g是一个苹果,一个重100g,另一个重150g,那么1+1=2.5?
如果我要加的是今天的这个苹果和昨天的同一个苹果,那么1+1=1?
所以结果不同是因为我们所框定的规则不同吧。

标签:函数,Effective,Point,多态,C++,virtual,析构,SpecialString,class
From: https://blog.csdn.net/weixin_44387866/article/details/145155348

相关文章

  • gesp(C++五级)(5)洛谷:B3929:[GESP202312 五级] 小杨的幸运数
    gesp(C++五级)(5)洛谷:B3929:[GESP202312五级]小杨的幸运数题目描述小杨认为,所有大于等于aaa的完全平方数都是他的超级幸运数。小杨还认为,所有超级幸运数的倍数都是他......
  • gesp(C++五级)(6)洛谷:B3930:[GESP202312 五级] 烹饪问题
    gesp(C++五级)(6)洛谷:B3930:[GESP202312五级]烹饪问题题目描述有NNN种食材,编号从00......
  • C++ 和 Tesseract OCR 识别验证码
    安装TesseractOCR首先,我们需要安装TesseractOCR。根据不同操作系统进行安装。在Ubuntu上安装:bashsudoaptupdatesudoaptinstalltesseract-ocrsudoaptinstalllibleptonica-devsudoaptinstalllibtesseract-dev在Windows上安装:下载TesseractOCR的Wi......
  • 【C++】反向迭代器
    反向迭代器一.源码及框架分析二.反向迭代器实现代码1.ReverseIterator.h2.Vector.h3.List.h4.Test.cpp一.源码及框架分析SGI-STL30版本源代码,反向迭代器实现的核心源码在stl_iterator.h中,反向迭代器是一个适配器,各个容器中再适配出自己的反向迭代器。下面截出vector......
  • 封装,继承,多态
    在Java中,封装、继承和多态是面向对象编程(OOP)的三大核心特性。它们共同构成了面向对象编程的基础,帮助开发者编写出模块化、可重用和可扩展的代码。以下是它们的详细讲解:1. 封装(Encapsulation)定义封装是指将对象的属性和行为(方法)包装在一起,并对外隐藏内部实现细节,只暴露必......
  • Qt/C++ 基于回调模式的海康3D相机开发流程详解(附工程源码、开发文档下载链接)
    本文将基于海康3D相机SDK的回调模式,通过具体代码讲解如何完成从设备初始化到图像采集的完整流程。以下是标准的流程图和具体的开发步骤。一、开发流程概述流程分为以下几个关键步骤:运行环境初始化:调用MV3D_LP_Initialize(),初始化SDK运行环境。设备发现:调用MV3D_LP_Get......
  • VC6.0(VC++6.0)下载安装使用教程(建议新手收藏)
    微软原版的VC6.0已经不容易找到,网上提供的都是经过第三方修改的版本,删除了一些使用不到的功能,增强了兼容性。这里我们使用VC6.0完整绿色版,它能够支持一般的C/C++应用程序开发以及计算机二级考试。VC6.0完整绿色版下载地址:VC6.0下载地址该软件仅31M,下载快速,安装简单,无......
  • 《 C++ 点滴漫谈: 二十 》内存的权杖:C++ new 和 delete 的致胜之道
    摘要本文全面探讨了C++中的new和delete关键字及其在动态内存管理中的核心作用。从基本概念到底层实现,本文详细分析了其工作机制,并揭示了动态内存管理中的常见问题与陷阱,如内存泄漏和空悬指针。为解决这些问题,现代C++提供了智能指针和STL容器等高效替代方案,同时本......
  • c++ optimization
    Wemainlyusetheoptimizationtechniquespresentedin[7-9]andsomeotheronlinedocumentsinthisarea[7]WritingEfficientCandC++CodeOptimization,KoushikGhosh,[OnlineDocument],Availableon:http://www.codeproject.com/cpp/C___Code_Optimizat......
  • 打卡信奥刷题(599)用C++信奥P7852[普及组/提高] 「EZEC-9」Yet Another Easy Problem
    「EZEC-9」YetAnotherEasyProblem题目描述给定n,mn,mn,m,你需要输出一个长度为......