关于创建对象的一个小问题。说我有这两个类:
struct A{
A(){cout << "A() C-tor" << endl;}
~A(){cout << "~A() D-tor" << endl;}
};
struct B : public A{
B(){cout << "B() C-tor" << endl;}
~B(){cout << "~B() D-tor" << endl;}
A a;
};
在main中我创建了一个B
:
int main(){
B b;
}
请注意,B
来自A
,并且还有A
类型的字段。
我想弄明白这些规则。我知道在构造对象时首先调用它的父构造函数,反之则在破坏时调用它。
字段(本例中为A a;
)怎么样?创建B
时,它何时会调用A
的构造函数?我还没有定义初始化列表,是否有某种默认列表?如果没有默认列表?关于破坏的同样问题。
答案 0 :(得分:74)
class
开头。如果有多个基础class
es,则构造从最左边的基数开始。 (旁注:如果存在virtual
继承,则会给予更高的偏好。)class
本身无论初始化列表如何,呼叫顺序都是这样的:
class A
的构造函数class B
将构建名为a
(类型为class A
)的字段class B
的构造函数答案 1 :(得分:22)
假设没有虚拟/多重继承(这会使事情变得复杂),那么规则很简单:
要记住的一件重要事情是,直到第4步,对象还不是其类的实例,因为它只有在构造函数的执行开始后才能获得此标题。这意味着如果在成员的构造函数期间抛出异常,则不执行该对象的析构函数,但是仅销毁已构造的部分(例如成员或基类)。这也意味着如果在成员或基类的构造函数中调用对象的任何虚拟成员函数,则调用的实现将是基础实现,而不是派生实现。 另一个要记住的重要事项是初始化列表中列出的成员将按照它们在类中声明的顺序构建,而不是按照它们在初始化列表中出现的顺序构建(幸运的是,如果列出成员,大多数正常的编译器都会发出警告与班级宣言的顺序不同。)
另请注意,即使在执行构造函数代码期间this
对象已经获得其最终类(例如,关于虚拟分派),也不会调用类的析构函数,除非构造函数完成执行。只有当构造函数完成执行时,对象实例才是实例中真正的第一类公民...在此之前只是一个“想成为实例”(尽管有正确的类)。
破坏以完全相反的顺序发生:首先执行对象析构函数,然后它失去它的类(即从对象上的这一点被视为基础对象)然后所有成员以反向声明顺序销毁,最后是基础类销毁过程执行到最抽象的父级。对于构造函数,如果在基类或成员析构函数中调用对象的任何虚拟成员函数(直接或间接),则执行的实现将是父实例,因为在类析构函数完成时对象丢失了其类标题。
答案 2 :(得分:7)
基类始终在数据成员之前构建。数据成员按照在类中声明的顺序构造。此顺序与初始化列表无关。初始化数据成员时,它将查看参数的初始化列表,如果没有匹配则调用默认构造函数。始终以相反的顺序调用数据成员的析构函数。
答案 3 :(得分:3)
基类构造函数总是先执行。因此,当您编写语句B b;
时,首先调用A
的构造函数,然后调用B
类构造函数。因此构造函数的输出将为按以下顺序排列:
A() C-tor
A() C-tor
B() C-tor
答案 4 :(得分:1)
#include<iostream>
class A
{
public:
A(int n=2): m_i(n)
{
// std::cout<<"Base Constructed with m_i "<<m_i<<std::endl;
}
~A()
{
// std::cout<<"Base Destructed with m_i"<<m_i<<std::endl;
std::cout<<m_i;
}
protected:
int m_i;
};
class B: public A
{
public:
B(int n ): m_a1(m_i + 1), m_a2(n)
{
//std::cout<<"Derived Constructed with m_i "<<m_i<<std::endl;
}
~B()
{
// std::cout<<"Derived Destructed with m_i"<<m_i<<std::endl;
std::cout<<m_i;//2
--m_i;
}
private:
A m_a1;//3
A m_a2;//5
};
int main()
{
{ B b(5);}
std::cout <<std::endl;
return 0;
}
本例中的答案是2531.如何在此处调用构造函数:
调用相同的析构函数:
在这个例子中,构造m_A1&amp; m_A2与初始化列表顺序的顺序无关,但与它们的声明顺序无关。
答案 5 :(得分:0)
修改后的代码输出为:
A() C-tor
A() C-tor
B() C-tor
~B() D-tor
~A() D-tor
~A() D-tor