构造函数
调用时间: 创建一个对象是 会自动调用 构造函数.
如果 创建 的是一个指针变量是不会调用构造函数, 当 new 一个新空间时,就会自动调用构造函数.
构造函数的名字和类名相同,一个类中可以定义多个构造函数.不同的构造函数 之间 是重载关系.
如果一个类没有定义构造函数,则系统会自动给该类定义一个构造函数 称为 默认构造函数.
而一旦 一个类中 有构造函数,则不会再给这个类 定义默认的构造函数.
构造函数 可以定义在类内,也可以定义在类外. 若定义在类外,则要加作用域运算符,表明这个构造函数 是属于那个类.
如果一个类定义了构造函数,但是还想有默认的构造函数 可以用 default
例
cstu() = default;
一个构造函数的执行相当于 一个赋值的过程,而不是初始化的过程.
然而,对部分数据类型不能进行赋值,只能进行初始化, 如 const,引用.
这就引出了 初始化列表.
初始化列表 (类的一个属性)
每一个构造函数都有一个 与之绑定的初始化列表. 默认为 空
作用: 对类中成员进行初始化;
和构造函数的区别 : 构造函数是赋值,初始化列表 是进行初始化.
与构造函数执行的顺序 : 初始化列表 比 构造函数先执行.
初始化的顺序 : 谁先定义给谁先初始化,于初始化列表的顺序无关.(最好令构造函数初始值的顺序于成员声明的顺序保持一致,而且如果可能的话,尽量避免使用某些成员初始化其他成员).
初始化列表 在 构造函数后,以冒号隔开.多个初始化成员以逗号隔开
例:
class Cstu
{
public:
int a;
double f;
// 用12 给a初始化, 用12.12 给 f 初始化
Cstu() : a(12),f(12.12)
{
de
}
};
还可以通过参数进行初始化
class Cstu
{
public:
int a;
double f;
//也可以通过参数初始化
//用 d 给a 初始化,用 c 给 f 初始化.
Cstu(int d,double c) : a(d),f(c)
{
}
};
const 和 引用,或者属于某种未提供默认构造函数的类类型的初始化
错误操作
#include<iostream>
using namespace std;
class Cstu
{
private:
const int a;
int & b;
public:
/*Cstu(int c,int d) : a(c),b(d)
{
}*/
Cstu(int c,int d)
{
a = c;
b = d;
}
void display()
{
cout << "a = " << a << " b = " << b << endl;
}
};
int main()
{
Cstu stu1(1,2);
stu1.display();
return 0;
}
正确操作
#include<iostream>
using namespace std;
class Cstu
{
private:
const int a;
int & b;
public:
Cstu(int c,int d) : a(c),b(d)
{
}
/* Cstu(int c,int d)
{
a = c;
b = d;
}*/
void display()
{
cout << "a = " << a << " b = " << b << endl;
}
};
int main()
{
Cstu stu1(1,2);
stu1.display();
return 0;
}
注意:
构造函数不能被声明为 const,当我们创建一个const 对象时,直到构造函数完成初始化过程,这个对象才能获取 常量属性
还有一个特殊的类型: 静态常量整型数据成员可以在类中初始化.
尽管 一个类会有多个对象,但这个 数据成员是 对多有 对象共享的.
综上: 建议使用构造函数初始值.在很多类中,初始化和赋值的区别事关底层效率问题.前者直接初始化数据成员,后者先初始化在赋值.
除了效率问题,还有 一些数据成员必须被初始化.