7.为多态基类声明虚析构函数 1.为多态基类声明虚析构函数 code1: class A{ public: int* a; A():a(new int(5)) {} ~A(){ delete a; } }; class B:public A { public: int *b; B():b(new int(10)) {} ~B(){ delete b; } }; int main(int argc, char const *argv[]) { B *bb=new B; A* aa=bb; dele…
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 这个规则只适用于polymorphic(带多态性质的)base class身上.这种base class的设计目的是为了用来“通过base class接口处理derived class对象”.假如我们在程序中设计factory(工厂)函数,让它返回base class指针,指向新生成的derived class对象,假设base class有个non-virtu…
一.C++明确指出:当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未定义——实际执行时通常发生的是对象的derived成分没有被销毁!(注:使用基类引用派生类的方式使用多态,由于引用只是对原对象的一个引用或者叫做别名,其并没有分配内存,对其引用对象内存的销毁,将由原对象自己负责,所以使用引用的时候,如果析构函数不为virtual,那么也不会发生derived成员没有销毁的情况) 例如: class b…
C++明确指出:当派生类对象是由一个基类指针释放的,而基类中的析构函数不是虚函数,那么结果是未定义的.其实我们执行时其结果就是:只调用最上层基类的析构函数,派生类及其中间基类的析构函数得不到调用. #include <iostream> using namespace std; class TimeKeeper { public: TimeKeeper(); ~TimeKeeper(); }; TimeKeeper::TimeKeeper() { cout << "Con…
引言: 我们都知道类的一个很明显的特性是多态,比如我们声明一个水果的基类: class Fruit { public: Fruit() {}; ~Fruit(){}; } 那么我们根据这个Fruit基类可以派生出以下的子类: class Apple:public Fruit{}; class Orange:public Fruit{}; 那么问题来了,如果我们想经由一个基类指针去删除一个派生类Apple,且我们有以下的方法 Fruit * foo(){ Apple * p = new Apple…
class TimeKeeper { public: TimeKeeper() ; ~TimeKepper() ; ... } ; class AtomicClock:public TimeKeeper{...}// 原子钟 class WaterClock:public TimeKeeper{...}// 水钟 class WristWatch:public TimeKeeper{...}// 腕表 根据工厂模式,会返回一个base class指针指向新生成的derived class对象.…
一个函数的返回值为基类指针,而当指针指向一个派生类对象,接下来派生类对象被这个基类指针删除的时候,就出现了局部销毁的问题.因为C++指出,当派生类经由一个基类指针被删除,而该基类指针带着一个non-virtual析构函数,其结果未有定义.实际的执行情况是派生类的析构函数没有执行,然而基类的成分通常会被销毁,于是早晨了诡异的"局部销毁"对象.这是造成资源泄漏.败坏数据结构.在调试器上浪费许多时间的绝佳途径==. 给基类一个virtual析构函数就可以消除这个问题了. 如果基类不含virt…
在继承中,基类的析构函数需要定义为虚析构函数数否则: (1)当派生类对象经由一个base类指针删除时,而这个base类的析构函数不是虚函数时,其结果是未定义的. (2)这样做会导致derived类部分的成员没有被销毁,即造成局部销毁的对象. (3)从而造成资源泄漏,败坏之数据结构,在调试器上浪费去多时间. 记住: (1)带多态性质的base class 应该声明一个virtual析构函数,如果base class带有任何的虚函数,那么应该声明虚析构函数. (2)一般析构函数的调用是.最深层次的析…
来自<Effective C++>条款07:为多态声明virtual析构函数 当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义——实际执行时通常发生的是对象的derived成分没被销毁,而其基类成分通常会被销毁,于是造成了一个诡异的“局部销毁”对象. 解决这个问题的做法很简单:给base class一个virtual析构函数.此后删除derived class对象就会如你想要的那般销毁整个对象…
class TimeKeeper { public: TimeKeeper(); // ~TimeKeeper(); 错误,此作为一个基类,被继承了.其继承类被delete后,基类被销毁,但继承类可能没被销毁 virtual ~TimeKeeper();//必须声明为virtual类型才可以. protected: private: };   class AtomicClock: public TimeKeeper{}; //继承   TimeKeeper* ptk = getTimeKeepe…
polymorphic(带多态性质的)base classes应该声明一个virtual析构函数.如果class带有任何virtual函数,它就应该拥有一个virtual析构函数. Classes的设计目的如果不是作为base classes使用,或不是为了具备多态性(polymorphically),就不该声明virtual析构函数.…
Declare destructors virtual in polymorphic base classes.   [原理] C++指出,当derived class对象经由一个由base class类型的指针删除时,如果这个base class 拥有一个non-virtual的析构函数,那个析构的结果将是未定义的.即通常情况下是该对象的base class成分会被析构掉,但是其derived class成分没有被销毁,甚至连derived class的析构函数也不会被调用. 于是形成一个被“…
注意:polymorphic base class 应该具有虚析构函数,如果class带有任何virtual函数,也应具有虚析构函数 class不具备polymorphic属性则不应该声明virtual 析构函数 1.老生常谈,如果一个类需要被使用为base calss 则为它声明 "virtual析构函数",确保删除一个"指向派生类对象的基类指针" 时内存完整删除 2.对于不需要使用为base class的类,反而不声明virtual 函数是最好的,如果你的类只具…
问题聚焦: 已经对一个对象执行了delete语句,还会发生内存泄漏吗? 先来看个demo: // 计时器类 class TimeKeeper { public: TimeKeeper(); ~TimeKeeper(); }; class AtomicClock: public TimeKeeper { ...... }; // 原子钟 class WaterClock: public TimeKeeper { ...... }; // 水表 class WristWatch: public Ti…
当基类确定被继承的时候,析构函数声明为virtual是必须的 当返回的派生类的指针或引用的时候,调用析构函数容易发生内存泄漏 当基类作为抽象类使用,声明pure virtual析构函数 析构函数的顺序————派生类的析构函数先被调用(先析构基类成员) 构造函数的顺序————派生类的构造函数先被调用(先构造基类成员)…
1.考虑下面的需要,需要一个工厂方法.工厂方法的规则是:在堆上分配一个子类对象,并返回父类指针.使用完毕,delete父类指针.如果父类的析构方法不是virtual,将直接调用父类的析构方法,导致局部销毁的对象,父类成分销毁了,子类成分没有销毁. 2.如果类中有virtual方法,意味着面向抽象编程,也就是会有父类指针指向子类对象,因此这种情况下,必定需要一个virtual析构方法. 3.如果类中没有virtual方法,为了节省空间,析构方法是non-virtual方法.也就意味着,这个类不作为…
NOTE: 1.polymorphic(多态性质的)base classes 应该声明一个virtual 析构函数.如果class带有任何virtual函数,它就应该拥有一个virtual析构函数. 2.Classes 的设计目的如何不是作为bases classes 使用,或不是为了具备多态性(polymorphically),就不该声明为virtual 析构函数.…
主要内容: 1.C++类继承中的构造函数和析构函数 2.C++多态性中的静态绑定和动态绑定 3.C++多态性中析构函数声明为虚函数 1.C++类继承中的构造函数和析构函数 在C++的类继承中, 建立对象时,首先调用基类的构造函数,然后在调用下一个派生类的构造函数,依次类推: 析构对象时,其顺序正好与构造相反: 具体参考文章:http://www.cnblogs.com/AndyJee/p/4575385.html 2.C++多态性中的静态绑定和动态绑定 对象的静态类型:对象在声明是采用的类型,在…
1. 继承体系中关于对象释放遇到的问题描述 1.1 手动释放 关于时间记录有很多种方法,因此为不同的计时方法创建一个TimeKeeper基类和一些派生类就再合理不过了: class TimeKeeper { public: TimeKeeper(); ~TimeKeeper(); ... }; class AtomicClock: public TimeKeeper { ... }; class WaterClock: public TimeKeeper { ... }; class Wrist…
基类声明的指针变量和引用类型变量可以指向派生类的对象,而反过来派生类的指针却不能指向基类变量. 这与基类和派生类之间,被允许的赋值方向是相反的. 但是从逻辑上很容易推敲其合理性.…
如果想在派生类中定义与基类成员同名的成员,则可以使用new关键字把基类成员隐藏起来. 如果不适应new关键字,在派生类中定义一个与基类成员同名的成员,编译器将产生警告信息,如下代码演示: public class Animals { public void Eat() { Console.WriteLine("动物吃方法"); } } public class Horse:Animals { //想在派生类中也定义一个Eat方法,则会收到警告信息 public void Eat() {…
基类指针指向子类对象. 子类对象必须位于堆.因此为了避免泄漏内存资源,当指针不使用时,delete掉每一个对象非常重要.但是如果基类的析构函数不声明为virtual.那么指向子类对象的指针delete时,析构掉的成分都是基类的,而子类的成分没有被识别出来,而未被析构掉.这样就造成资源浪费.给基类析构函数声明为virtual,那么delete对象时,就会是你希望的那样,它会销毁整个对象,包括所有继承类(drived class)的成分.析构时调用顺序:先调用最深层次的派生类的析构函数,依次向上调用…
虚基类       在说明其作用前先看一段代码 class A{public:    int iValue;}; class B:public A{public:    void bPrintf(){cout<<"This is class B"<<endl;};}; class C:public A{public:    void cPrintf(){cout<<"This is class C"<<endl;};}…
#include <iostream> using namespace std; class Father { public: ~Father() { cout << "Father's Desconstruct Called. " << endl; } }; class Son: public Father { public: ~Son() { cout << "Son's Desconstruct Called "…
 1.多态 面向对象程序设计中,多态性表现为: (1)重载多态:函数重载.运算符重载: (2)运行多态:通过基类的指针(或引用)调用不同派生类的同名函数,表现出不同的行为: (3)模板多态:参数多态,通过一个模板得到不同的函数或不同的类,具有不同的特性和不同的行为: 2.同名覆盖与重载 (1)override(同名覆盖) 在类的继承中才会出现,多个函数的原型是相同的. (2)overload(重载) 在同一作用域范围内,由参数个数或类型不同的多个同名函数构成. 3.虚函数 原因:通过指针调用成员…
十八. 继承和多态 ● 继承的概念 继承(inheritance): 以旧类为基础创建新类, 新类包含了旧类的数据成员和成员函数(除了构造函数和析构函数), 并且可以派生类中定义新成员. 形式: class <派生类名>: <继承方式1> <基类名1> <继承方式2> <基类名2> ..., <继承方式n> <基类名n> { <派生类新定义的成员> } #include <iostream> usi…
五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的. 2.在遇到通过基类指针或引用调用虚函数的语句时,首先根据指针或引用的静态类型来判断所调函数是否属于该class或者它的某个public 基类,如果 属于再进行调用语句的改写:  C++ Code  1   (*(p->_vptr[slotNum]))(p, arg-list); 其中p是基类指针…
多态 虚函数 在类的定义中,前面有virtual关键字的成员函数就是虚函数. virtual关键字只用在类定义里的函数声明中,写函数体时不用. 构造函数和静态成员函数不能是虚函数. 多态的表现形式 基类指针指向派生类 派生类的指针可以赋给基类指针. 通过基类指针调用基类和派生类中的同名虚函数时: (1)若该指针指向一个基类的对象,那么被调用的是基类的虚函数. (2)若该指针指向一个派生类的对象,那么被调用的是派生类的虚函数. 这种机制叫做"多态". class CBase { publ…
一.C++多态 C++的多态包括静态多态和动态多态.静态多态包括函数重载和泛型编程,动态多态包括虚函数.静态多态是指在编译期间就可以确定,动态多态是指在程序运行时才能确定. 二.虚函数 1.虚函数为类的非静态成员函数,访问权限一般为public.函数声明时,在返回值前加virtual关键字,函数定义时不需要加virtual.父类定义的虚函数,子类在继承时,可以对虚函数重新定义,当然子类的函数应该与父类虚函数一样,只是函数实现不一样.我们用父类的指针指向子类的实例,然后通过父类的指针可以调用实际子…
this指针: 1)对象中没有函数,只有成员变量 2)对象调用函数,通过this指针告诉函数是哪个对象自己谁. #include<iostream> using namespace std; class Shape { public: //void cal_display(Shape* this) void cal_display(){ display(); this->display(); } private: ; }; class Circle:public Shape { priv…