析构函数

条款7 为多态基类声明virtual析构函数

亡梦爱人 提交于 2019-12-07 07:26:45
条款7 为多态基类声明virtual析构函数 如有以下关系,不使用virtual关系会出现资源泄漏 //base class class TimeKeeper { public : virtual TimeKeeper* getTimeKeeper() { return NULL; } }; class AtomTimeKeeper: public TimeKeeper { public : AtomTimeKeeper(){ pData= new char [ 100 ]; } TimeKeeper* getTimeKeeper() { return myAtom; } private : int a; char * pData; static AtomTimeKeeper* myAtom; }; AtomTimeKeeper* AtomTimeKeeper::myAtom = new AtomTimeKeeper(); int main() { AtomTimeKeeper myAtom; TimeKeeper* pTime=myAtom. getTimeKeeper(); delete pTime; //这将引起部分内存泄漏 return 0 ; } 来源: CSDN 作者: awawsese765 链接: https://blog.csdn.net/awawsese765

《Effective C++》学习笔记条款07 为多态基类声明virtual析构函数

十年热恋 提交于 2019-12-07 07:24:42
条款 07 :为多态基类声明 virtual 析构函数 当基类的指针指向派生类的对象的时候,当我们使用完,对其调用 delete 的时候,其结果将是未有定义 —— 基类 成分通常会被销毁,而派生类的充分可能还留在堆里。这可是形成资源泄漏、败坏之数据结构、在调试器上消费许多 时间。 消除以上问题的做法很简单:给基类一个 virtual 析构函数。此后删除派生类对象就会如你想要的那般。 任何类只要带有 virtual 函数都几乎确定应该也有一个 virtual 析构函数。 如果一个类不含 virtual 函数,通常表示它并不意图被用做一个基类,当类不企图被当做基类的时候,令其析构函 数为 virtual 往往是个馊主意。因为实现 virtual 函数,需要额外的开销( 指向虚函数表的指针 vptr )。 STL 容器都不带 virtual 析构函数,所以最好别派生它们。 请记住: (1) 带有多态性质的基类应该声明一个virtual析构函数。如果一个类带有任何virtual函数,它就应该拥个 virtual 析 构 函数。 (2) 一个类的设计目的不是作为基类使用,或不是为了具备多态性,就不该声明virtual析构函数。 2013.11.28 下午 来源: CSDN 作者: ccwRadar 链接: https://blog.csdn.net/A09211008/article

[Effective C++系列]-为多态基类声明Virtual析构函数

混江龙づ霸主 提交于 2019-12-07 07:23:40
Declare destructors virtual in polymorphic base classes. [原理] C++指出,当derived class对象经由一个由base class类型的指针删除时,如果这个base class 拥有一个non-virtual的析构函数,那个析构的结果将是未定义的。即通常情况下是该对象的base class成分会被析构掉,但是其derived class成分没有被销毁,甚至连derived class的析构函数也不会被调用。 于是形成一个被“局部销毁”的对象,造成资源泄漏。 [示例] 例如: class car { public : car(); ~ car(); ... }; class diesel_car : public car {…}; class solar_car: public car {…}; class electric_car : public car {…}; 当客户代码中使用汽车对象时,如果他不关心使用的是具体哪一类汽车这个细节,那么我们可以设计一个工厂函数(或者工厂类)负责创建一个汽车对象,该工厂函数返回一个base class指针或者引用,指向新生成的derived class对象: car* get_car(); 为遵守工厂函数的规矩,返回的对象必须位于heap

Effective C++——条款7(第2章)

末鹿安然 提交于 2019-12-07 07:23:23
条款07: 为多态基类声明 virtual 析构函数 Declare destructors virtual in polymorphic base classes 设计以下时间基类TimeKeeper: class TimeKeeper { public: TimeKeeper(); ~TimeKeeper(); }; class AtomicClock : public TimeKeeper { ... }; class WaterClock : public TimeKeeper { ... }; class WristWatch : public TimeKeeper { ... }; 许多客户只想在程序中使用时间,不想操心时间如何计算等细节,这是可以设计factory(工厂)函数,返回指针指向一个计时对象. Factory函数会"返回一个base class指针,指向新生成的derived class对象" : TimeKeeper *getTimeKeeper(); // 返回一个指针,指向TimeKeeper派生类的动态分配对象 为遵守factory函数的规矩,将getTimeKeeper()返回的对象必须位于heap.因此为了避免泄露内存和其他资源,将factory函数返回的每一个对象适当地 delete 掉很重要: TimeKeeper *ptk =

Effective C++:条款07

我的梦境 提交于 2019-12-07 07:23:08
Effective C++:条款07:为多态基类声明virtual析构函数 (Declare destructors virtual in polymorphic base classes.) polymorphic(带多态性质的)base classes应该声明一个virtual析构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构函数。 Classes的设计目的如果不是作为base classes使用,或不是为了具备多态性(polymorphically),就不应该声明virtual析构函数。 这个问题在实践中偶尔会碰到,设计一个TimeKeeper基类和一些派生类来记录时间: 1 class TimeKeeper 2 { 3 public: 4   TimeKeeper (); 5   ~TimeKeeper(); 6 7 }; 8 9 class AtomicClock: public TimeKeeper {}; //原子钟 10 class WaterClock: public TimeKeeper {}; //水钟 在使用时,我们可能会使用factory工厂方法: 1 TimeKeeper* getTimeKeeper();//返回一个指针,指向一个派生类的动态分 配的对象 2 3 TimeKeeper* ptk =

Effective C++读书笔记(5)

徘徊边缘 提交于 2019-12-07 07:22:49
条款07:为多态基类声明virtual析构函数 Declare destructors virtual inpolymorphic base classes 建立一个 TimeKeeper基类,并为不同的计时方法建立派生类: class TimeKeeper { public: TimeKeeper(); virtual ~TimeKeeper(); ... }; class AtomicClock: public TimeKeeper { ... };//原子钟 class WaterClock: public TimeKeeper { ... };//水钟 class WristWatch: public TimeKeeper { ... };//腕表 TimeKeeper* getTimeKeeper(); //返回一个指针,指向一个TimeKeeper派生类的动态分配对象 TimeKeeper *ptk = getTimeKeeper(); //从TimeKeeper继承体系获得一个动态分配对象 ... //运用它 delete ptk; //释放它,避免资源泄漏 很多客户只是想简单地取得时间而不关心如何计算的细节,所以一个 factoryfunction (工厂函数) ——返回一个指向新建派生类对象的基类指针的函数——可以被用来返回一个指向计时对象的指针

c++ 虚析构函数[避免内存泄漏]

China☆狼群 提交于 2019-12-07 07:19:19
c++ 虚析构函数: 虚析构函数 (1)虚析构函数即:定义声明析构函数前加virtual 修饰, 如果将基类的析构函数声明为虚析构函数时, 由该基类所派生的所有派生类的析构函数也都自动成为虚析构函数。 (2)基类指针pbase 指向用new动态创建的派生类对象child时,用“delete pbase;”删除对象分两种情况: 第一,如果基类中的析构函数为虚析构函数,则会先删除派生类对象,再删除基类对象 第二, 如果基类中的析构函数为非虚析构函数,则只会删除基类对象,不会删除派生类对象,这样便出现了内存泄漏了 #include <iostream> using namespace std; #include < string > /////////////////////////// / class Base { public : #if 0 virtual ~Base(); // in Child::~Child() in Base::~Base() #else ~Base(); // in Base::~Base() 存在内存泄漏的危险 #endif }; Base:: ~ Base() { cout << " in Base::~Base() " << endl; } /////////////////////////// / class Child: public Base

【C++学习】 C++ 虚析构(virtual destructor)浅析

元气小坏坏 提交于 2019-12-07 07:19:02
【C++学习】C++ 虚析构(virtual destructor)浅析 先来看一段简单的代码(main.cpp): #include <iostream> using namespace std ; class CBase{ public : CBase() { cout << "CBase construct ... " <<endl; } virtual ~CBase() { cout << "CBase destructor ... " <<endl; } }; class CSon : public CBase{ public : CSon(){ cout << "CSon construct ... " <<endl; } ~CSon(){ cout << "CSon destructor ... " <<endl; } }; void test() { CBase* pObj = new CSon(); delete pObj; } int main( int argc, char * argv[]) { test(); return 0 ; } 运行结果为: 大家都能理解,而将virtual ~CBase() 的virtual 去掉, 将输出: 大家将看到,子类的析构函数没有被调用。 那为什么加了virtual就会调用子类的析构函数呢? 这是本文的主题。

C++虚析构函数详解

喜夏-厌秋 提交于 2019-12-07 07:18:42
当派生类的对象从内存中撤销时一般先调用派生类的析构函数,然后再调用基类的析构函数。但是,如果用new运算符建立了临时对象,若基类中有析构函数,并且定义了一个指向该基类的指针变量。在程序用带指针参数的delete运算符撤销对象时,会发生一个情况:系统会只执行基类的析构函数,而不执行派生类的析构函数。 [例12.3] 基类中有非虚析构函数时的执行情况。为简化程序,只列出最必要的部分。 #include <iostream> using namespace std; class Point //定义基类Point类 { public: Point( ){} //Point类构造函数 ~Point(){cout<<"executing Point destructor"<<endl;} //Point类析构函数 }; class Circle:public Point //定义派生类Circle类 { public: Circle( ){} //Circle类构造函数 ~Circle( ){cout<<"executing Circle destructor"<<endl;} //Circle类析构函数 private: int radius; }; int main( ) { Point *p=new Circle; //用new开辟动态存储空间 delete p; /

C++虚析构函数、纯虚析构函数

穿精又带淫゛_ 提交于 2019-12-07 07:18:14
虚析构函数 析构函数的工作方式是: 最底层的派生类(most derived class)的析构函数最先被调用,然后调用每一个基类的析构函数 。 因为在C++中,当一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,则结果是未定义的。运行时比较有代表性的后果是对象的派生部分不会被销毁。然而,基类部分很可能已被销毁,这就导致了一个古怪的“部分析构”对象,这是一个泄漏资源。排除这个问题非常简单:给基类一个虚析构函数。于是,删除一个派生类对象的时候就有了你所期望的正确行为。将销毁整个对象,包括全部的派生类部分。 但是, 一般如果不做基类的类的析构函数一般不声明为虚函数,因为虚函数的实现要求对象携带额外的信息 ,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具有一种被称为 vptr(virtual table pointer,虚函数表指针)的指针的形式。vptr 指向一个被称为 vtbl(virtual table,虚函数表)的函数指针数组,每一个包含虚函数的类都关联到 vtbl。当一个对象调用了虚函数,实际的被调用函数通过下面的步骤确定:找到对象的 vptr 指向的 vtbl,然后在 vtbl 中寻找合适的函数指针。这样子会使类所占用的内存增加。 定义纯虚析构函数(pure virtual destructor) 纯虚成员函数通常没有定义