本文最后更新于:1 天前
(一)概念:
创建类的对象的时候,编译系统需要对象分配内存空间,完成数据成员的初始化工作并请求其他资源,此时,编译系统自动调用构造函数来完成这些工作。
因此,构造函数是在创建类的对象时使用,它的核心作用是初始化对象的数据成员和分配内存。
(二)原型和特点:
构造函数的原型为:**类名::类名(参数表):初始化列表 { 构造函数体 }
——所有倾斜内容表示在构造函数中此内容可选,不是必要的。
——参数表即为所有的传入形参
——初始化列表结构为:数据成员名(某形参名),数据成员名(某形参名)...
——构造函数体可执行相关操作可为cout<<某些信息,对数据成员的某些操作等等。
构造函数的特点:
-
名字与类名相同,允许设定参数,但是不允许设置返回值(包括void)。
-
构造函数是编译系统在实例化一个对象时自动执行的,不需要手动调用(当然也可以主动手动调用)。调用后会对对象的数据成员进行初始化。
定义自己的无参构造函数实际上是有用构造函数
-
构造函数可以重载,但是对象的实例化只会使用其中的一个构造函数(参数类型和个数能够最佳匹配),且实例化后不会再次执行构造函数,另外,重载构造函数后不允许出现二义性情况。
-
在未定义构造函数时,编译系统生成一个无用的默认构造函数,无用的默认构造函数不含参数,不做任何初始化工作。
一旦定义了自己的构造函数,系统不会自己生成无用的默认的无参构造函数,但是仍然可以自己指定系统生成无用默认无参构造函数。
(三)分类:
-
默认构造函数,又名缺省构造函数,分为有用和无用两种,是不需要显式指定实参的构造函数——即原型为无参构造函数。
-
初始化构造函数——有参数。
-
复制(拷贝构造函数(不显式指定时有默认的复制构造函数)。
-
转换构造函数
(四)基本用法:
1.默认构造函数:
形式:
-
“类名() =default;”的形式或者不存在任何构造函数——指定无用默认构造函数。
-
"类名(){ 函数体 }"的形式——指定有用默认构造函数
调用时,因默认构造参数不需要形参,直接声明类的对象即可(切记不要在后面跟“()”!)。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #include <iostream> using namespace std; class Time { private: int hour; int minute; int sec; public: void set_time() { cin >> hour >> minute >> sec; return; } void show_time() { cout << hour << ":" << minute << ":" << sec << endl; }
}; int main() { Time t1; t1.set_time(); t1.show_time(); return 0; }
|
2.带参构造函数:
形式:类名:构造函数名(参数表):初始化列表 { 构造函数体 }
如果数据成员中有数组,要在构造函数体中用语句对其进行赋值,不能用初始化列表进行初始化。
以其他类作为数据成员时,需要在初始化列表进行初始化。初始化列表需要首先调用成员类的构造函数,再初始化自身的数据成员。
通常带参构造函数需要重载。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <iostream> using namespace std; class Time { private: int hour; int minute; int sec; public: Time() { hour = minute = sec = 0; } Time(int i1, int i2, int i3) :hour(i1), minute(i2), sec(i3) {} Time(int h) :hour(h) { minute = sec = 0; } Time(int h, int m) :hour(h), minute(m) { sec = 0; } void set_time() { cin >> hour >> minute >> sec; return; } void show_time() { cout << hour << ":" << minute << ":" << sec << endl; }
}; int main() { Time t1(1,2,3); t1.set_time(); t1.show_time(); return 0; }
|
3.复制(拷贝)构造函数:
此内容较多,单开一篇博客,详见c++类——复制构造函数
4.转换构造函数:
形式:类名:构造函数名(单一参数):初始化列表 { 构造函数体 }
转换构造函数用于将其他类型的变量,隐式转换为本类对象。
传入的单一参数不能是本类的const引用,否则为复制构造函数。
转换构造函数可以与运算符重载配合使用(运算符重载详见c++类——运算符重载)。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| #include <iostream> using namespace std; class Time { private: int hour; int minute; int sec; public: Time() { hour = minute = sec = 0; } Time(int i1, int i2, int i3) :hour(i1), minute(i2), sec(i3) {} Time(int h) :hour(h) { minute = sec = 0; }
void set_time() { cin >> hour >> minute >> sec; return; } void show_time() { cout << hour << ":" << minute << ":" << sec << endl; } Time operator+(const Time& temp) { return Time(this->hour + temp.hour, this->minute + temp.minute, this->sec + temp.sec); } }; int main() { Time t1=4; t1.show_time(); t1 = t1 + 5; t1.show_time(); return 0; }
|
附:关键字explicit:
因为隐式类型转换往往会导致工程中出现一些奇奇怪怪的bug,所以,c++中定义了关键字explicit来杜绝转换构造函数的隐式类型转换。
关键字explicit只能用于修饰转换构造函数(也就是只含一个参数的类构造函数)或参数表中仅有一个没有默认参数的带参构造函数(等效于转换构造函数),其作用是表明该转换构造函数是显式的,而不是隐式的。
如果想指定默认情况为隐式的声明,可在前面指定关键字implicit。(不常用)
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <iostream> using namespace std; class Time { private: int hour; int minute; int sec; public: Time() { hour = minute = sec = 0; } Time(int i1, int i2, int i3) :hour(i1), minute(i2), sec(i3) {} explicit Time(int h) :hour(h) { minute = sec = 0; }
void set_time() { cin >> hour >> minute >> sec; return; } void show_time() { cout << hour << ":" << minute << ":" << sec << endl; } Time operator+(const Time& temp) { return Time(this->hour + temp.hour, this->minute + temp.minute, this->sec + temp.sec); } }; int main() { Time t1= static_cast<Time>(4); t1.show_time(); t1 = t1 + 5; t1.show_time(); return 0; }
|