目录
构造函数
概念
每个类都分别定义了它的对象被初始化的方式,类通过一个或几个特殊的成员函数来 控制其对象的初始化过程, 这些函数叫做构造函数( constrnctor ) 。
特性
- 构造函数的任务是初始化类对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数。
- 构造函数的名字和类名相同。和其他函数不一样的是,构造函数没有返回类型;
- 构造函数必须是public的,否则与创建对象就调用相违背,这个编译器会报错。
- 不同于其他成员函数,构造函数不能被声明成const 的(参见7 .1.2 节,第231 页) 。当我们创建类的一个const对象时, 直到构造函数完成初始化过程,对象才能真正取得其“常量“属性。因此,构造函数在const 对象的构造过程中可以向其写值。
构造函数的简单书写和使用
//Time.cpp
Time::Time(int tmphour, int tmpmin, int tmpsec)
{
hour = tmphour;
minute = tmpmin;
second = tmpsec;
millisecond = 0;
}
//Time.h
class Time
{
public:
int hour;
int minute;
int second;
private:
int millisecond;
public:
Time(int tmphour, int tmpmin, int tmpsec);
};
//test.cpp
void func1()
{
Time myTime(12, 13, 52);//创建类对象
Time myTime2(12, 13, 52);
Time myTime3 = Time(12, 13, 52);
Time myTime4{ 12,13,52 };
Time myTime5 = { 12,13,52 };
//Time myTime6();//错误
//Time myTime7(12, 13);//错误
//没有合适的构造函数
}
合成的默认构造函数
一个类并没有定义任何构造函数,之前使用了该类的对象的程序仍然可以正确地编译和运行。
因为编译器会创建构造函数编译器创建的构造函数又被称为合成的默认构造函数。(只有当类没有声明任何构造函数时,编译器才会自动地生成默认构造函数。)
重载构造函数
类可以包含多个构造函数, 和其他重载函数差不多,不同的构造函数之间必须在参数数量或参数类型上有所区别。
重载函数简单示例
//Time.cpp
Time::Time(int tmphour, int tmpmin, int tmpsec)
{
hour = tmphour;
minute = tmpmin;
second = tmpsec;
millisecond = 0;
std::cout << "调用了Time::Time(int tmphour, int tmpmin, int tmpsec)构造函数" << std::endl;
}
Time::Time()
{
hour = minute = second = millisecond = 0;
std::cout << "调用了Time::Time()构造函数" << std::endl;
}
//Time.h
class Time
{
public:
int hour;
int minute;
int second;
private:
int millisecond;
public:
Time(int tmphour, int tmpmin, int tmpsec);
Time();
};
//test.cpp
void func2()
{
Time myTime1 = Time();
//Time myTime2();//错误编译器会认为你在声明一个Time myTime2()的函数
Time myTime3 = Time{};
Time myTime4{};
Time myTime5 = {};
}
注意Time myTime2();的写法会导致歧义:
编译器会认为你在声明一个名为 mytime 的函数:返回值类型:Time(你的自定义类)参数列表:空(() 表示无参数)
因此,这实际上是一个函数声明,而非创建 Time 类的对象。
图中含有默认实参的带三个参数的构造函数和只带两个参数的构造函数编译器无法做出区分。
构造函数初始化列表
Sales_data(const std : : string & s) : bookNo(s) { }
Sales_ data(const std::str ing& s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(p* n) { }
冒号以及冒号和花括号之间的代码,其中花括号定义了(空的)函数体。我们把新出现的部分称为构造函数初始化列表也叫构造函数初始值列表
它负责为新创建的对象的一个或几个数据成员赋初值。构造函数初始值是成员名字的一个列表,每个名字后面紧跟括号括起来的(或者在花括号内的)成员初始值。不同成员的初始化通过逗号分隔开来。
=default
在C++11新标准中,如果我们需要默认的行为,那么可以通过在参数列表后面写上=default来要求编译器生成构造函数。
1.和声明写在一起写在类内部
class tmp2
{
public:
int i = 0;
int j = 0;
tmp2() = default;
};
2.作为定义写在类外部
tmp.h
class tmp1
{
public:
int i = 0;
int j = 0;
tmp1();
};
tmp.cpp
tmp1::tmp1() = default;
=delete
=delete意思为删除的,通知编译器(以及我们代码的读者),我们不希望定义这些成员。
与=default不同,=delete必须出现在函数第一次声明的时候。我们可以对任何函数指定=delete
class test
{
public:
int i = 0;
test() = delete;
};
void f3()
{
test obj;//无法引用test的默认构造函数,它是已删除的函数
}
参考书籍:
C++ Primer中文版 第5版作 者: (美)李普曼(Lippman,S.B.),(美)拉乔伊(Lajoie,J.),(美)默(Moo,B.E.) 著 王刚,杨巨峰 译,出版社: 电子工业出版社,ISBN: 9787121155352
本文是学习过程中参照C++primer结合自己的理解所写的笔记,如有纰漏还请指出,谢谢