类的析构及虚析构探究

正常析构及析构在多继承基类中产生的不足

  1. #include <iostream>
  2. using namespace std;
  3. //////////////////////////////////////////////////////////////////////////
  4. // 正常析构解决不了父类new子类时析构函数调用的问题
  5. // 也就是构造函数被调用了四次,而析构函数却被调用了三次
  6. //
  7. // 正常析构不能解决父子类同台出现的某些极端情况
  8. /*
  9. class A
  10. class B
  11. class A
  12. class B
  13. first delete A
  14. class ~A
  15. second delete B
  16. class ~B
  17. class ~A
  18. */
  19. class A
  20. {
  21. public:
  22. A()
  23. {
  24. cout << "class A" << endl;
  25. }
  26. ~A()
  27. {
  28. cout << "class ~A" << endl;
  29. }
  30. };
  31. class B: public A
  32. {
  33. public:
  34. B()
  35. {
  36. cout << "class B" << endl;
  37. }
  38. ~B()
  39. {
  40. cout << "class ~B" << endl;
  41. }
  42. };
  43. int main1()
  44. {
  45. A* a = new B();
  46. B* b = new B();
  47. cout << "first delete A" << endl;
  48. delete a;
  49. cout << "second delete B" << endl;
  50. delete b;
  51. return 0;
  52. }

虚析构能解决上述所产生的问题

  1. #include <iostream>
  2. using namespace std;
  3. //////////////////////////////////////////////////////////////////////////
  4. // 用虚基类析构函数能解决正常析构函数不能解放完的问题
  5. /*
  6. class AA
  7. class BB
  8. class AA
  9. class BB
  10. fir delete delete
  11. class ~BB
  12. class ~AA
  13. sec delete delete
  14. class ~BB
  15. class ~AA
  16. */
  17. class AA
  18. {
  19. public:
  20. AA()
  21. {
  22. cout << "class AA" << endl;
  23. }
  24. virtual ~AA()
  25. {
  26. cout << "class ~AA" << endl;
  27. }
  28. };
  29. class BB :public AA
  30. {
  31. public:
  32. BB()
  33. {
  34. cout << "class BB" << endl;
  35. }
  36. ~BB()
  37. {
  38. cout << "class ~BB" << endl;
  39. }
  40. };
  41. int main()
  42. {
  43. AA* a = new BB();
  44. BB* b = new BB();
  45. cout << "fir delete delete" << endl;
  46. delete a;
  47. cout << "sec delete delete" << endl;
  48. delete b;
  49. return 0;
  50. }

来自为知笔记(Wiz)

时间: 2024-08-27 13:40:34

类的析构及虚析构探究的相关文章

C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构

一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型,我们如果想通过一个父类指针调用父类.子类中的同名函数的话,这个函数是有要求的: 在父类中,eat函数声明之前必须要加virtual声明eat()函数为虚函数. 一旦某个函数被声明为虚函数,那么所有派生类(子类)中eat()函数都是虚函数. 为了避免你在子类中写错虚函数,在C++11中,你可以在函数

避免构造/析构函数调用虚函数(转)

不要在类的构造或者析构函数中调用虚函数,因为这种调用不会如你所愿,即使成功一点,最后还会使你沮丧不已.如果你以前是一个Java或者C#程序员,请密切注意本节的内容-这正是C++与其它语言的大区别之一. 假设你有一个为股票交易建模的类层次结构,例如买单,卖单,等等.为该类交易建立审计系统是非常重要的,这样的话,每当创建一个交易对象,在审计登录项上就生成一个适当的入口项.这看上去不失为一种解决该问题的合理方法: class Transaction {// 所有交易的基类 public: Transa

虚析构基类函数

考虑以下代码 class Ref { public: virtual ~Ref() { cout << "~Ref()" << endl; } }; class People :public Ref { public: ~People() { cout << "~People()" << endl; } }; 以下代码输出什么? int main(int argc, char *argv[]) { { People h

关于类继承的构造与析构调用分析

总体结论:派生类的构造函数在创建对象时调用,调用顺序如下: 1.调用虚基类的构造函数(若有多个虚基类,调用顺序为继承的顺序.): 2.调用基类的构造函数(若有多个基类,调用顺序为继承的顺序.): 3.调用类类型的成员对象的构造函数(调用顺序为定义的顺序): 4.调用自身的构造函数. 析构函数的调用顺序一般和构造函数的调用顺序相反,但分如下几种情况: 1.当父类的指针 new一个子类的临时对象时.若父类的析构不是虚函数,则delete的时候不调用子类的析构,只调用父类的析构:    若父类的析构是

虚析构和纯虚析构

虚析构和纯虚析构的共性 1.可以解决父类指针释放子类对象 2.都需要具体的函数实现 虚析构和纯虚析构的区别 如果是纯虚析构,则该类属于抽象类,无法实例化对象 虚析构语法 virtual ~类名(){} 纯虚析构 virtual ~类名() = 0 纯虚析构的类外实现 类名::~类名(){} 1 #include<bits/stdc++.h> 2 #include<iostream> 3 using namespace std; 4 5 class Animal 6 { 7 publ

[转载]析构函数的虚析构和非虚析构调用的差别

代码示例: 非虚析构的情况下. #include <stdio.h> #include <iostream> using namespace std; class A { public: A() { std::cout << "A is created." << std::endl; } ~A() { std::cout << "A is deleted." << std::endl; } };

C++——虚析构

目的: //只执行了 父类的析构函数//向通过父类指针 把 所有的子类对象的析构函数 都执行一遍//向通过父类指针 释放所有的子类资源 方法:在父类的析构函数前+virtual关键字 #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; //虚析构函数 class A { public: A() { p = new char[20]; strcpy(p, "obja"); print

C++ 派生类对象的构造与析构过程

C++ 派生类对象的构造与析构过程 因为基类的成员变量和派生类的成员变量在内存中的连续的(下面程序会验证这一点),如下图所示: 所以构造派生类对象的时候,构造成员变量的过程就像入栈一样: 那么很自然,派生类对象析构的时候就是出栈的过程,先进后出,后进先出: 下边一个简单的程序验证这个结论: #include <iostream> using namespace std; class base{ int a; public: base(const int& a):a(a){cout<

C++ 多重继承,虚析构确定

来个例子就明了了: #include<iostream> using namespace std; class Base1 { public: virtual ~Base1(){ cout<<"Base1"<<endl; } }; class Base2 { public: virtual ~Base2(){ cout<<"Base2"<<endl; } }; class D1:public Base1{