c++中不同场景构造函数的次序问题:

xiaoxiao2021-02-28  38

1.普通类的构造函数: (1)首在定义类时传参数指针this到构造函数 (2)按类中数据成员声明的次序一一进行分配内存空间并初始化 (3)执行构造函数的函数体   普通类的析构函数: (1)首先执行函数体 (2)对成员变量释放空间 2.继承与派生的构造函数 (1)首在定义类时传参数指针this到构造函数 (2)依照基类在构造函数中的定义次序调用基类的构造函数,初始化他们的成员(从左到右) (3)按类中数据成员声明的次序一一进行分配内存空间并初始化 (4)执行构造函数的函数体   继承与派生的构造函数:Derived::Derived(const Derived&v):Base(v){} (1)执行次序与构造函数相同   继承与派生的析构函数:次序与虚构函数相反 例子: #include<iostream> using namespace std; class A { public: A(){ cout<<"A"<<endl;} ~A(){cout<<"~A"<<endl;} }; class B:public A { A *p; public: B(){ cout<<"B";p=new A();} ~B(){ cout<<"~B";delete p;} }; int main() { B obj; return 0; } 输出:ABA~B~A~A 3.虚基类的构造函数 (1)如果该派生类有直接或间接的虚基类。则先执行虚基类的构造函数 (2)如果有其他基类,则按照他们在继承中声明列表中出现的次序。分别执行他们的构造函数,但是构造过程中不执行他们的虚基类的构造函数 (3)对派生类中新增成员进行初始化 (4)执行构造函数函数体 例子: #include <iostream> using namespace std; class A { int x; public: A(int a){x=a;} void Display() { cout<<x<<endl; } }; class B:virtual public A { int y; public: B(int a,int b):A(a) { y=b; } void Display() { cout<<y<<endl; } }; class C:virtual public A { int z; public: C(int a,int b):A(a) { z=b; } void Display() { cout<<z<<endl; } }; class D:public B,public C { int m,n; public: D(int a,int b,int c,int d):B(c,a),C(c,b),A(c) { m=d; n=a; } void Display() { A::Display(); 14 B::Display(); 12 C::Display(); 13 cout<<m<<","<<n<<endl; } }; void main() { D dd(12,13,14,15); dd.Display(); } 输出:14 12 13 15 12 4.虚函数 (1)定义虚基类的成员函数为虚函数 (2)定义派生类同名函数同参数同返回值 (3)定义一个基类指针指向派生类 (4)通过使用指针动态绑定派生类的成员函数 例子: #include<iostream> using namespace std; class Base { public: Base() { Show(); } virtual void Show() { cout << "Base::Show" << endl; } void Print() { Show(); } virtual ~Base() { Show(); } }; class Derived :public Base { public: Derived () { Show(); } virtual void Show() { cout << "Derived::Show" << endl; } void Print() { Show(); } virtual ~Derived() { Show(); } }; void main() { Base b; Base* p = &b; p->Print(); Derived d; p = &d; p->Print(); } 输出: Base::Show Base::Show Base::Show Derived::Show Derived::Show Derived::Show Base::Show Base::Show 结论 在类被构造的时候,先执行虚拟继承的父类的构造函数,然后从左到右执行普通继承的父类的构造函数, 然后按照定义的顺序执行数据成员的初始化,最后是自身的构造函数的调用。析构函数与之完全相反,互成镜像。
转载请注明原文地址: https://www.6miu.com/read-19367.html

最新回复(0)