c++ 类默认成员函数以及成员初始化探索
1、类的默认成员函数
构造函数、析构函数、拷贝构造函数、赋值运算符重载、&操作符重载、const &重载 –参考链接
例子:
定义一个空类
class Empty
{
}
一个空的class在C++编译器处理过后就不再为空,编译器会自动地为我们声明一些成员函数,代码如下:
class Empty
{
public:
Empty();
Empty( constEmpty& );
~Empty();
Empty&operator=( const Empty& );
Empty*operator&();
const Empty*operator&() const;
};
2、成员初始化
利用默认构造函数初始化成员变量
#include<iostream>
class A
{
public:
A() = default;
void print() {
std::cout << "val_a: " << val_a << " &val_a: " << &val_a << std::endl;
std::cout << "val_b: " << val_b << " &val_b: " << &val_b << std::endl;
std::cout << "val_c: " << val_c << " &val_c: " << &val_c << std::endl;
}
static int val_static;
private:
int val_a;
int val_b;
int val_c ;
};
int A::val_static = 1;
int main()
{
A a;
a.print();
std::cout << "val_static: " << A::val_static << " &val_static: " << &A::val_static << std::endl;
}
- 利用vs debug模式中成员变量值没有初始化,其结果为:
val_a: -858993460 &val_a: 00DEFC30
val_b: -858993460 &val_b: 00DEFC34
val_c: -858993460 &val_c: 00DEFC38
val_static: 1 &val_static: 00CA6000
从上面结果可以看出,成员函数没有给初始值,值都为-858993460(0xcccccccc),且都有分配内存。
- 利用vs debug模式中成员变量值没有初始化,其结果为:
val_a: 0 &val_a: 0136FA68
val_b: 1988144199 &val_b: 0136FA6C
val_c: 17113088 &val_c: 0136FA70
val_static: 1 &val_static: 005B4018
从上面的结果可以看出,成员函数没有给初始值,值是随机给的,且都分配内存。
3、初始化成员的先后顺序
代码:(参考)
#include<iostream>
using namespace std;
class A
{
int a;
int b;
public:
A() :b(0), a(b + 2){ }
void print()
{
cout << "a = " << a << " ,b = " << b << endl;
}
};
int main()
{
A a;
a.print();
return 0;
}
运行结果:
a = 7476729 ,b = 0
从结果可值,类中成员变量初始化的先后次序与变量在类中被定义的先后次序有关,与构造函数中被初始化的先后顺序无关。
4、构造函数初始化调用顺序
参考
#include <iostream>
using namespace std;
class OBJ1{
public:
OBJ1(){ cout<<"OBJ1\n"; }
};
class OBJ2{
public:
OBJ2(){ cout<<"OBJ2\n";}
}
class Base1{
public:
Base1(){ cout<<"Base1\n";}
}
class Base2{
public:
Base2(){ cout <<"Base2\n"; }
};
class Base3{
public:
Base3(){ cout <<"Base3\n"; }
};
class Base4{
public:
Base4(){ cout <<"Base4\n"; }
};
class Derived :public Base1, virtual public Base2,public Base3, virtual public Base4
public:
Derived() :Base4(), Base3(), Base2(),Base1(), obj2(), obj1(){
cout <<"Derived ok.\n";
}
protected:
OBJ1 obj1;
OBJ2 obj2;
};
int main()
{
Derived aa;
cout <<"This is ok.\n";
return 0;
}
结果:
Base2 //虚拟基类按照被继承顺序初始化
Base4 //虚拟基类按照被继承的顺序
Base1 //非虚拟基类按照被继承的顺序初始化
Base3 //非虚拟基类按照被继承的顺序
OBJ1 //成员函数按照声明的顺序初始化
OBJ2 //成员函数按照声明的顺序
Derived ok.
This is ok.
由上可知,C++构造函数初始化按下列顺序被调用:
- 首先,任何虚拟基类的构造函数按照它们被继承的顺序构造;
- 其次,任何非虚拟基类的构造函数按照它们被继承的顺序构造;
- 最后,任何成员对象的构造函数按照它们声明的顺序调用;
|