c++父类,子类,成员变量的构造/析构顺序,以及创建对象时一些小细节
父类,子类,成员变量的构造/析构顺序:
- 先调用基类的构造函数
- 再调用子对象类(成员变量)的构造函数
- 最后调用派生类的构造函数
- 调用顺序与派生类构造函数冒号后面给出的初始化列表(Derived(): m1(), m2(), Base1(), Base2())没有任何关系,按照继承的顺序和变量再类里面定义的顺序进行初始化。 先继承Base2,就先构造Base2。先定义m2,就先构造m2。
- 析构函数调用顺序仍然与构造函数构造顺序相反。(成员和对象的析构函数调用顺序是:先调用对象的析构函数,然后再在析构函数里调用成员的析构函数)
如果自定义了构造函数,则编译器就不会自动生成默认构造函数,但仍会生成默认拷贝构造函数;
如果自定义了拷贝构造函数,则编译器就不会自动生成默认移动构造函数;
如果没有显示声明定义析构函数,则编译器会自动生成非虚版本的析构函数。
1. 父类型指针 a = new 子类型; delete a时,父/子类的构造/析构函数时如何调用的?
直接看下面例子:
1 #include <memory> 2 #include <iostream> 3 4 using namespace std; 5 6 class BF{ 7 public: 8 BF(){ cout << "base::base()\n";fun();} 9 virtual ~BF(){cout << "~base::base()\n";fun();} 10 virtual void fun(){cout << "base::fun() virtual\n";} 11 }; 12 13 class derive: public BF 14 { 15 17 public: 18 derive(){cout << "derive::derive()\n";fun();} 19 ~derive(){cout << "~derive::derive()\n";fun();} 20 virtual void fun(){cout << "derive::fun() virtual\n";} 21 }; 22 23 int main() 24 { 25 cout << "-------------------" << endl; 26 BF *b = new BF(); 27 delete b; 28 cout << "-------------------" << endl; 29 derive *d = new derive(); 30 delete d; 31 cout << "-------------------" << endl; 32 BF *bd = new derive(); 33 delete bd; 34 return 0; 35 36 }
运行结果:
-------------------
base::base()
base::fun() virtual
~base::base()
base::fun() virtual
-------------------
base::base()
base::fun() virtual
derive::derive()
derive::fun() virtual
~derive::derive()
derive::fun() virtual
~base::base()
base::fun() virtual
-------------------
base::base()
base::fun() virtual
derive::derive()
derive::fun() virtual
~derive::derive()
derive::fun() virtual
~base::base()
base::fun() virtual
结论: 类型A指针 a = new 类型B 时,无论类型A如何,都是调用类型B的构造函数来初始化,delete a时也是调用类型B的析构函数
2. C++创建类对象时(无参)后不加括号与加括号的区别(参考:https://www.cnblogs.com/traeyee/p/4892410.html)
直接看例子:
1 #include<iostream> 2 using namespace std; 3 4 class C{ 5 public: 6 C(){ 7 cout<<"Hello C++\n"; 8 }; 9 C(int m){ 10 cout<<"I love C++\n"; 11 }; 12 private: 13 int n; 14 }; 15 16 int main(){ 17 cout << "-------get parameter------" << endl; 18 C a(1); 19 cout << "-------get ()------" << endl; 20 C b(); 21 cout << "-------nothing------" << endl; 22 C c; 23 return 0; 24 }
运行结果:
-------get parameter------
I love C++
-------get ()------
-------nothing------
Hello C++
结论:
给参数时,调用相应的构造函数,在栈内存中实例化对象;
只有一个括号时……这尼玛是声明了一个返回该类对象的函数;
啥都没有只有对象名时,调用默认构造函数(如果没有定义默认构造函数则出错)。
3. C++中 new 一个对象 时加括号和不加括号的区别
1 #include<iostream> 2 using namespace std; 3 4 class C{ 5 public: 6 C(){ 7 cout<<"Hello C++\n"; 8 }; 9 C(int m){ 10 cout<<"I love C++\n"; 11 }; 12 private: 13 int n; 14 }; 15 16 int main(){ 17 cout << "-------get parameter------" << endl; 18 C* a = new C(1); 19 cout << "-------get ()------" << endl; 20 C* b = new C(); 21 cout << "-------nothing------" << endl; 22 C* c = new C; 23 return 0; 24 }
运行结果:
-------get parameter------
I love C++
-------get ()------
Hello C++
-------nothing------
Hello C++
结论:
传入参数时,会调用相应的构造函数;没有参数时,无论是否加括号,都会调用默认构造函数