C++构造函数的调用次序是:
基类的成员->基类的构造函数体->派生类的成员->派生类的构造函数体
C++析构函数的调用次序是:
派生类的析构函数->派生类的成员析构->基类的析构函数->基类的成员析构
#include <iostream>
class ParentMember
{
public:
ParentMember()
{
std::cout<<"ParentMember Construct"<<std::endl;
}
~ParentMember()
{
std::cout<<"ParentMember Destruct"<<std::endl;
}
};
class Parent
{
public:
Parent()
{
std::cout<<"Parent Construct"<<std::endl;
}
~Parent()
{
std::cout<<"Parent Destruct"<<std::endl;
}
private:
ParentMember parentMember;
};
int main()
{
cout<<"Construct过程: "<<endl;
Parent *p = new Parent;
cout<<""<<endl;
cout<<"Destruct过程: "<<endl;
delete p;
}
运行结果:
Construct过程:
ParentMember Construct
Parent Construct
Destruct过程:
Parent Destruct
ParentMember Destruct
从运行结果不难看出:
1、在构造过程中,执行顺序为: 类成员->类的构造函数体。
若断点调试,会发现,首先运行到构造函数的 '{'处,就会掉头先调用成员变量了。
2、在析构过程中,执行顺序为:类的析构函数 -> 类的成员析构
基类、派生类构造的顺序
基类、派生类析构的顺序
#include <iostream>
class Parent
{
public:
Parent()
{
std::cout<<"Parent Construct"<< std::endl;
}
~Parent()
{
std::cout<<"Parent Destruct"<< std::endl;
}
};
class Child: public Parent
{
public:
Child()
{
std::cout<<"Child Construct"<< std::endl;
}
~Child()
{
std::cout<<"Child Destruct"<< std::endl;
}
};
int main()
{
std::cout<<"Construct过程: "<< std::endl;
Parent *p = new Child;
std::cout<<" "<< std::endl;
std::cout<<"Destruct过程: "<< std::endl;
delete p;
}
运行结果:
Construct过程:
Parent Construct
Child Construct
Destruct过程:
Parent Destruct
从运行结果不难看出:
1、在构造过程中,执行顺序为: 先基类,后子类,即:基类的构造函数体 -> 子类的构造函数体
若断点调试,会发现,首先运行到子类构造函数的 '{'处,就会掉头先调用基类成员变量了。
2、在析构过程中,执行顺序为: 怎么仅基类呢?
执行顺序本应该为:先子类,后基类,即子类的析构函数 -> 基类的析构函数。但实际运行效果我们不难发现,在最后释放指针p所指向的对象时,只释放了基类的部分,没有释放派生类的部分。这是因为,指针p声明时是基类的指针,而基类的析构函数不是虚函数,所以调用那个析构函数是在编译时确定的。如果要执行正确的析构顺序,需要将基类的析构函数定义为 virtual, 这样派生类的析构函数就自动是virtual的了,在最后释放指针p时,按照RTTI,执行p所指真实对象的析构函数。
class Parent
{
public:
Parent()
{
std::cout<<"Parent Construct"<< std::endl;
}
virtual ~Parent() //增加virtual
{
std::cout<<"Parent Destruct"<< std::endl;
}
};
修改后运行结果:
Construct过程:
Parent Construct
Child Construct
Destruct过程:
Child Destruct
Parent Destruct
#include <iostream>
class ParentMember
{
public:
ParentMember()
{
std::cout<<"ParentMember Construct"<< std::endl;
}
~ParentMember()
{
std::cout<<"ParentMember Destruct"<< std::endl;
}
};
class Parent
{
public:
Parent()
{
std::cout<<"Parent Construct"<< std::endl;
}
~Parent()
{
std::cout<<"Parent Destruct"<< std::endl;
}
private:
ParentMember parentMember;
};
class ChildMember
{
public:
ChildMember()
{
std::cout<<"ChildMember Construct"<< std::endl;
}
~ChildMember()
{
// std::cout<<"ChildMember Destruct"<< std::endl;
}
};
class Child: public Parent
{
public:
Child()
{
std::cout<<"Child Construct"<< std::endl;
}
~Child()
{
std::cout<<"Child Destruct"<< std::endl;
}
private:
ChildMember childMember;
};
int main()
{
std::cout<<"Construct过程: "<< std::endl;
和Parent *p = new Child;
std::cout<<""<< std::endl;
std::cout<<"Destruct过程: "<< std::endl;
delete p;
}
运行结果:
Construct过程:
ParentMember Construct
Parent Construct
ChildMember Construct
Child Construct
Destruct过程:
Parent Destruct
ParentMember Destruct
从运行结果不难看出,在构造过程中,执行顺序为:
析构函数执行顺序未按预期执行,详见:示例2尾部详细说明。修改方案,详见:示例4.
class Parent
{
public:
Parent()
{
std::cout<<"Parent Construct"<< std::endl;
}
virtual ~Parent() //增加virtual
{
std::cout<<"Parent Destruct"<< std::endl;
}
private:
ParentMember parentMember;
};
运行结果:
Construct过程:
ParentMember Construct
Parent Construct
ChildMember Construct
Child Construct
Destruct过程:
Child Destruct
//ChildMember Destruct //未输出???
Parent Destruct
ParentMember Destruct
不难看出以下规律:
C++构造函数的调用次序是:
基类的成员->基类的构造函数体->派生类的成员->派生类的构造函数体
C++析构函数的调用次序是:
派生类的析构函数->派生类的成员析构->基类的析构函数->基类的成员析构