[关闭]
@lishuhuakai 2015-05-21T16:55:36.000000Z 字数 3923 阅读 2048

c++类的函数调用顺序

c++


  1. /*
  2. 1 C++中提供了初始化列表对成员变量进行初始化
  3. 2 使用初始化列表出现原因:
  4. 1.必须这样做:
  5. 如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,
  6. 而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,
  7. 如果没有初始化列表,那么他将无法完成第一步,就会报错。
  8. 2、类成员中若有const修饰,必须在对象初始化的时候,给const int m 赋值
  9. 当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化,
  10. 因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。
  11. */
  12. //总结 构造和析构的调用顺序
  13. #include "iostream"
  14. using namespace std;
  15. class ABC
  16. {
  17. public:
  18. ABC(int a, int b, int c)
  19. {
  20. this->a = a;
  21. this->b = b;
  22. this->c = c;
  23. printf("==========addr:%x===============\n", this);
  24. printf("a:%d,b:%d,c:%d \n", a, b, c);
  25. printf("ABC construct ..\n");
  26. printf("================================\n");
  27. }
  28. ~ABC()
  29. {
  30. printf("==========addr:%x===============\n", this);
  31. printf("a:%d,b:%d,c:%d \n", a, b, c);
  32. printf("~ABC() ..\n");
  33. printf("================================\n");
  34. }
  35. protected:
  36. private:
  37. int a;
  38. int b;
  39. int c;
  40. };
  41. class MyD
  42. {
  43. public:
  44. MyD() :abc1(1, 2, 3), abc2(4, 5, 6), m(100)
  45. {
  46. printf("==========addr:%x===============\n", this);
  47. cout << "MyD()" << endl;
  48. printf("================================\n");
  49. }
  50. ~MyD()
  51. {
  52. printf("==========addr:%x===============\n", this);
  53. cout << "~MyD()" << endl;
  54. printf("================================\n");
  55. }
  56. protected:
  57. private:
  58. ABC abc1; //c++编译器不知道如何构造abc1
  59. ABC abc2;
  60. const int m;
  61. };
  62. int run()
  63. {
  64. MyD myD;
  65. return 0;
  66. }
  67. int main()
  68. {
  69. run();
  70. system("pause");
  71. return 0;
  72. }
  73. /**
  74. ==========addr:3ffd60=============
  75. a:1,b:2,c:3
  76. ABC construct ..
  77. ================================
  78. ==========addr:3ffd6c=============
  79. a:4,b:5,c:6
  80. ABC construct ..
  81. ================================
  82. ==========addr:3ffd60=============
  83. MyD()
  84. ================================
  85. ==========addr:3ffd60=============
  86. ~MyD()
  87. ================================
  88. ==========addr:3ffd6c=============
  89. a:4,b:5,c:6
  90. ~ABC() ..
  91. ================================
  92. ==========addr:3ffd60=============
  93. a:1,b:2,c:3
  94. ~ABC() ..
  95. ================================
  96. */

其实很好理解,调用子函数时会做压栈处理,子函数里面的变量也按照栈的思想来理解即可,先入栈的先调用构造函数,又因为栈的先进后出的特性,因此,先进栈的后析构。
可以好好分析一下下面的代码和结果:

  1. //对象做函数参数
  2. //1 研究拷贝构造
  3. //2 研究构造函数,析构函数的调用顺序
  4. //总结 构造和析构的调用顺序
  5. #include <iostream>
  6. using namespace std;
  7. class ABCD
  8. {
  9. public:
  10. ABCD(int a, int b, int c)
  11. {
  12. this->a = a;
  13. this->b = b;
  14. this->c = c;
  15. printf("==========addr:%x==========\n", this);
  16. printf("ABCD()构造函数, a:%d,b:%d,c:%d \n", this->a, this->b, this->c);
  17. }
  18. ~ABCD()
  19. {
  20. printf("==========addr:%x==========\n", this);
  21. printf("~ABCD()析构函数,a:%d,b:%d,c:%d \n", this->a, this->b, this->c);
  22. }
  23. int getA()
  24. {
  25. return this->a;
  26. }
  27. protected:
  28. private:
  29. int a;
  30. int b;
  31. int c;
  32. };
  33. class MyE
  34. {
  35. public:
  36. MyE() :abcd1(1, 2, 3), abcd2(4, 5, 6), m(100)
  37. {
  38. printf("==========addr:%x==========\n", this);
  39. cout << "MyE无参构造函数" << endl;
  40. }
  41. ~MyE()
  42. {
  43. printf("==========addr:%x==========\n", this);
  44. cout << "MyE析构函数" << endl;
  45. }
  46. MyE(const MyE & obj) :abcd1(7, 8, 9), abcd2(10, 11, 12), m(100)
  47. {
  48. printf("==========addr:%x==========\n", this);
  49. printf("MyD拷贝构造\n");
  50. }
  51. public:
  52. ABCD abcd1;
  53. ABCD abcd2;
  54. const int m;
  55. };
  56. int doThing(MyE mye1)
  57. {
  58. //printf("doThing函数");
  59. cout << endl;
  60. return 0;
  61. }
  62. int run2()
  63. {
  64. MyE myE;
  65. doThing(myE);
  66. return 0;
  67. }
  68. int run3()
  69. {
  70. printf("run3 start..\n");
  71. //ABCD abcd = ABCD(100, 200, 300);
  72. //若直接调用构造函数哪
  73. //想调用构造函数对abc对象进行再复制,可以吗?
  74. //在构造函数里面调用另外一个构造函数,会有什么结果?
  75. ABCD(400, 500, 600); //临时对象的生命周期
  76. printf("run3 end\n");
  77. return 0;
  78. }
  79. int main()
  80. {
  81. run2();
  82. //run3();
  83. system("pause");
  84. return 0;
  85. }
  86. /**
  87. ABCD()构造函数, a:1,b:2,c:3
  88. ==========addr:2cf8c4==========
  89. ABCD()构造函数, a:4,b:5,c:6
  90. ==========addr:2cf8b8==========
  91. MyE无参构造函数
  92. ==========addr:2cf7ac==========
  93. ABCD()构造函数, a:7,b:8,c:9
  94. ==========addr:2cf7b8==========
  95. ABCD()构造函数, a:10,b:11,c:12
  96. ==========addr:2cf7ac==========
  97. MyD拷贝构造
  98. ==========addr:2cf7ac==========
  99. MyE析构函数
  100. ==========addr:2cf7b8==========
  101. ~ABCD()析构函数,a:10,b:11,c:12
  102. ==========addr:2cf7ac==========
  103. ~ABCD()析构函数,a:7,b:8,c:9
  104. ==========addr:2cf8b8==========
  105. MyE析构函数
  106. ==========addr:2cf8c4==========
  107. ~ABCD()析构函数,a:4,b:5,c:6
  108. ==========addr:2cf8b8==========
  109. ~ABCD()析构函数,a:1,b:2,c:3
  110. */

也可以顺带分析一下下面的代码:

  1. #include "iostream"
  2. using namespace std;
  3. class MyTest
  4. {
  5. public:
  6. MyTest(int a, int b, int c)
  7. {
  8. this->a = a;
  9. this->b = b;
  10. this->c = c;
  11. }
  12. MyTest(int a, int b)
  13. {
  14. this->a = a;
  15. this->b = b;
  16. MyTest(a, b, 100);
  17. }
  18. ~MyTest()
  19. {
  20. printf("MyTest~:%d, %d, %d\n", a, b, c);
  21. }
  22. protected:
  23. private:
  24. int a;
  25. int b;
  26. int c;
  27. public:
  28. int getC() const { return c; }
  29. void setC(int val) { c = val; }
  30. };
  31. int main()
  32. {
  33. MyTest t1(1, 2);
  34. printf("c:%d", t1.getC()); //请问c的值是?
  35. system("pause");
  36. return 0;
  37. }
  38. /**
  39. MyTest~:1, 2, 100
  40. c:-858993460
  41. */
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注