#include<iostream>
using namespace std;
class A{
public:
A(){cout<<"A"; }
~A(){cout<<"~A"; }
};
class B:public A{
A*p;
public:
B(){cout<<"B"; p=new A(); }
~B(){cout<<"~B"; delete p; }
};
int main(void)
{
B obj;
system("pause");
return 0;
}
此串代码的输出结果是什么,又是如何得到的?望指教,万分感谢!
输出结果为 ABA~B~A~A
。
一开始 B obj 调用了 B 的默认构造函数,所以首先会调用父类 A 的构造函数(输出 A),然后输出 B,最后初始化 p 有药调用 A 的构造函数,所以又输出 A。
最后,B 会被销毁,也就是调用析构函数,因此先输出 ~B
,然后 delete p 会输出~A
,最后还需要调用父类的析构函数,所以再次输出 ~A
。
需要注意的就是,对于子类来说,构造函数是父->子,而析构函数是子->父。
代码有错误,第六行应该是 A(),你丢了A
修改后运行结果
ABA~B~A~A
也就是先构造obj,这个需要调用A,再调用B,在调用B的时候构造了p所以又调用了A,析构首先调用析构函数 ~B,里面删除 p 调用了 ~A,最后调用 ~A
>>> set1={{'Name': 'Runoob', 'Age': 7, 'Class': 'First'},4,5,6}
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
set1={{'Name': 'Runoob', 'Age': 7, 'Class': 'First'},4,5,6}
TypeError: unhashable type: 'dict'
>>>
问题解答:
类的构造函数和析构函数调用顺序问题,如何得到结果?
首先需要明确一个概念:在C++中,类在实例化时会调用构造函数,当实例被销毁时会调用析构函数。如果类中存在父类和成员对象,会涉及到构造函数和析构函数的调用顺序问题。
在C++中,类的构造函数的调用顺序与实例化的顺序相关,即先实例化的先调用构造函数。析构函数的调用顺序与实例化的顺序相反,即后实例化的先调用析构函数。
如果存在多个继承关系,调用顺序为:先父类,再子类;如果存在组合关系(成员对象),构造函数和析构函数的调用顺序为:先成员对象,再本体。
为了验证上述结论,以下给出一个示例代码:
#include <iostream>
using namespace std;
class A{
public:
A() { cout << "A constructor" << endl; }
virtual ~A() { cout << "A destructor" << endl; }
};
class B : public A{
public:
B() { cout << "B constructor" << endl; }
~B() { cout << "B destructor" << endl; }
};
class C : public A{
public:
C() { cout << "C constructor" << endl; }
~C() { cout << "C destructor" << endl; }
};
class D{
public:
D() { cout << "D constructor" << endl; }
~D() { cout << "D destructor" << endl; }
};
class E{
public:
E() { cout << "E constructor" << endl; }
~E() { cout << "E destructor" << endl; }
};
class F{
public:
F() { cout << "F constructor" << endl; }
~F() { cout << "F destructor" << endl; }
private:
D d;
E e;
};
class G : public F{
public:
G() { cout << "G constructor" << endl; }
~G() { cout << "G destructor" << endl; }
private:
A* a;
B b;
C c;
};
int main()
{
G* g = new G();
delete g;
return 0;
}
输出结果为:
D constructor E constructor F constructor A constructor C constructor B constructor G constructor G destructor B destructor C destructor A destructor F destructor E destructor D destructor
可以看到,构造函数的调用顺序为:D-E-F-A-C-B-G;析构函数的调用顺序为:G-B-C-A-F-E-D,符合之前的调用顺序总结。
需要注意的细节或特殊情况:
如果类中存在const成员对象,需要使用初始化列表来进行初始化,而不是在构造函数中初始化。
如果类中有指针成员,需要注意在析构函数中进行内存释放。
如果类中存在异常处理,需要注意在析构函数中处理异常。
总之,在编写类的构造函数和析构函数时,需要考虑到上述特殊情况,以保证程序的正确性和健壮性。