再谈构造函数
- 初始化列表
例如:
class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
虽然上面的构造函数调用之后,对象中已经有了一个初始值,但是不能将其称作为类对象成员的初始化,构造函数体中的语句只能将其称作为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。
若要初始化类对象成员,可采用以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式,这种称为初始化列表,但是采用这种方式会产生一些问题,因为初始化列表中的成员出现次序,并不代表真正的初始化次序,成员变量的初始化次序是其在类中的声明次序,例如:
class Date
{
public:
Date(int year=1900, int month=3, int day=3)
: _year(year)
//初始化,赋值不是初始化,因为初始化只能进行一次,而赋值可以进行多次
, _month(_day)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d(2019, 3, 2);
return 0;
}
它的结果是2019,随机值,2,因为他是按照类中成员的声明顺序来初始化的,在初始化_month时,由于_day还没有初始化,因此为随机值。因此最好不要使用成员去初始化成员,因为在一些情况下有的成员还没有初始化。
注意
- 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
- 类中包含以下成员,必须放在初始化列表位置进行初始化:
引用成员变量,因为引用必须在定义时初始化,并且不能重新赋值
常量成员,包括const成员变量,因为常量只能初始化,不能赋值
没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化,例如:
class Time
{
public:
Time(int hour, int minute, int second)
:_hour(hour)
, _minute(minute)
, _second(second)
{
cout << "Time(int,int,int)" << endl;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
Date(int year)
:_year(year)//const修饰的变量必须在初始化列表中初始化
,_t(0,0,0)//没有默认构造函数的类类型必须在初始化列表处初始化
, _day1(_day)//引用类型必须在初始化列表中初始化,因为引用在定义时必须初始化,而且引用不能重新赋值
//在初始化列表中,不能使用this指针,因为此时对象还没有构造好,this指针是指向对象的,因此不能使用
{
_month = 2;
_day = 2;
}
void Display()
{
cout << this->_year << endl;
cout << this->_month << endl;
cout << this->_day << endl;
cout << this->_day1 << endl;
}
private:
const int _year;
int _month;
int _day;
int& _day1;
Time _t;
};
void Test()
{
Date d(2020);
d.Display();
}
int main()
{
Test();
return 0;
}
构造了一个Time类,它没有默认构造函数,显式构造函数是非全缺省构造函数,当在Date类中定义一个Time类的对象_t时,必须在Date类的初始化列表中对_t进行初始化,且const修饰的_year必须在初始化列表中初始化,引用类型也必须在初始化列表中初始化。
3.在初始化列表中,不能使用this指针,因为this指针是指向对象的,当前初始化列表中对象还没有构造成功,因此不能使用。在构造函数体中可以使用,因为此时对象已经构造完成。
4.在编译器编译期间,已经为主函数分配了栈空间,主函数在运行期间所需要的栈的大小用ebp和esp两个寄存器标记,这个空间已经包含了函数体的局部对象,但其实在构造函数调用之前,对象是不存在的,也就是没有构造对象,但已经分配好了对象所需空间。
- explicit关键字
用explicit修饰构造函数,将会禁止单参构造函数的隐式转换,也就是explicit只能修饰单参构造函数,意思是表明该构造函数是显式的,与之对应的是implicit&#x