virtual

C++中基类的析构函数为什么要用virtual虚析构函数

倾然丶 夕夏残阳落幕 提交于 2019-12-07 07:29:33
知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定。 关于动态绑定的讲解,请参阅: C++中的动态类型与动态绑定、虚函数、多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。 示例代码讲解 现有Base基类,其析构函数为非虚析构函数。Derived1和Derived2为Base的派生类,这两个派生类中均有以string* 指向存储其name的地址空间,name对象是通过new创建在堆上的对象,因此在析构时,需要显式调用delete删除指针归还内存,否则就会造成内存泄漏。 class Base { public: ~Base() { cout << "~Base()" << endl; } }; class Derived1 : public Base { public: Derived1():name_(new string("NULL")) {} Derived1(const

条款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

条款07:为多态基类声明virtual析构函数(悬挂指针)

不想你离开。 提交于 2019-12-07 07:24:21
重点: 带多态性质的基类应该声明一个虚析构函数,如果类带有任何虚函数,它就应该拥有一个虚析构函数 类的设计目的如果不是作为基类使用,或者不是为了具备多态性,就不应该声明虚析构函数。 多态性质的体现:使用基类的指针(引用)去调用派生类的对象。 如下:使用一个base指针,指向derived对象,然后delete base指针,想要调用派生类的析构函数。此时把base的析构函数设置为virtual,使用基类指针调用的时候发生了动态绑定,所以会调用派生类的析构函数,然后再调用基类的析构函数。 引入虚函数,会导致某一类中拥有了一个虚函数指针vptr,会带来额外的4B的内存消耗(在本机上),他会指向一个vtbl(virtual table虚表)。所以如果不是为了具备多态性,使用虚函数只会造成无畏的开销。 class base { public: base(int* _val) :val(_val) {} virtual ~base() { delete val; cout << "基类析构函数调用<<endl"; } int* val; }; class derivedbase { public: //dericed(int* _val2) :base(_val2),val2(_val2) {} ---1 derived(int* _val2) :base(NULL),val2(_val2)

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 =

【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:17:28
众所周知,在实现多态的过程中,一般将基类的析构函数设为virtual,以便在delete的时候能够多态的链式调用。那么析构函数是否可以设为纯虚呢? class CBase { public : CBase() { printf("CBase()\n"); } virtual ~CBase() = 0; }; 答案是可以,那么这样实现的目的是什么呢?当然是避免实例化。 但因为派生类不可能来实现基类的析构函数,所以 基类析构函数虽然可以标为纯虚,但是仍必须实现析构函数 ,否则派生类无法继承,也无法编译通过。 下面详细讨论: 一. 虚析构函数 我们知道,为了能够正确的调用对象的析构函数,一般要求具有层次结构的顶级类定义其析构函数为虚函数。因为在delete一个抽象类指针时候,必须要通过虚函数找到真正的析构函数。 如: [cpp] view plain copy print ? class Base { public : Base(){} virtual ~Base(){} }; class Derived: public Base { public : Derived(){}; ~Derived(){}; } void foo() { Base *pb; pb = new Derived; delete pb; } 这是正确的用法,会发生动态绑定,它会先调用Derived的析构函数

虚析构函数

十年热恋 提交于 2019-12-07 07:10:21
直接的讲,C++中基类采用virtual虚析构函数是为了防止内存泄漏。 具体地说, 如果派生类中申请了内存空间 ,并在其 析构函数中 对这些内存空间进行 释放 。假设 基类 中采用的是 非虚析构函数 ,当delete 基类指针指向的派生类对象时 就不会触发 动态绑定 ,因而 只会调用基类的析构函数 ,而 不会调用派生类的析构函数 。那么在这种情况下, 派生类中申请的空间就得不到释放从而产生内存泄漏 。如果基类中析构函数声明为虚函数,则delete基类指针指向的派生类对象时通过动态绑定能够调用派生类的虚构函数,先执行派生类析构函数的函数体,再执行基类析构函数的函数体。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。 示例 基类析构函数未声明虚函数 #include <iostream> using namespace std; class Base { public: ~Base(){cout<<"~Base()"<<endl;} }; class Derived:public Base { public: virtual ~Derived(){cout<<"~Derived()"<<endl;} }; void test() { Base* b=new Derived(); delete b; cin.get(); } 输出

C++中基类的析构函数为什么要用virtual虚析构函数

我怕爱的太早我们不能终老 提交于 2019-12-07 07:09:56
大家知道,析构函数是为了在对象不被使用之后释放它的资源,虚函数是为了实现多态。那么把析构函数声明为vitual有什么作用呢? 直接的讲, C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。 请看下面的代码: #include <iostream> using namespace std; class Base { public: Base() {}; //Base的构造函数 ~Base() //Base的析构函数 { cout << "Output from the destructor of class Base!" << endl; }; virtual void DoSomething() { cout << "Do something in class Base!" << endl; }; }; class Derived : public Base { public: Derived() {}; /