•构造函数
–和类名相同
–没有返回值类型
–只在建立对象的时候被自动调用一次
–调用构造函数的主要目的是初始化对象
•一个对象的创建过程:
–分配内存空间
–初始化成员变量,如果成员是对象,构造他
–调用构造函数
•默认的空参构造函数
构造函数的使用
•构造函数重载
–构造函数也是函数,拥有重载的特征
–重载的构造函数在构造对象时根据参数自动选择
•利用参数默认值简化构造函数
–构造函数也拥有函数参数默认值的特性
–使用默认值可以减少构造函数的个数
•构造函数的初始化列表
–初始化列表可以让构造函数在调用之前进行初始化工作
–如果类的成员变量是const或引用类型,使用初始化列表是不二选择
•实践中,类的声明和定义是分开的
–请试着将写的类分成头文件和实现两部分
<pre name="code" class="cpp">//构造方法
#pragma 在做游戏的公司里面初始化的方法有两种风格 一种是init这是本来做苹果转过来的 另外一种是在构造方法里面初始化 (这本来就是做C++的)
#include <iostream>
using namespace std;
//类
class Time{
//默认是私有的
int hour;
int min;
int sec;
//
void dida(){
sec++;
if (60 == sec) {
sec = 0;
min++;
}
if (60 == min) {
min = 0;
hour++;
}
if (24 == hour) {
hour = 0;
}
}
public:
#pragma 构造方法: 没有返回值 ,方法名与类名相同。构造方法在创建对象的时候一定会被动的调用一次。如果我们自己没有写构造方法,编译器会帮我们写一个无参的构造方法
//构造函数的参数可以给定默认值
/*
Time (int h = 0,int m = 0,int s = 0){
cout << "Time (int h,int m,int s)在构造方法中初始化成员变量" << endl;
//通常在构造方法里面去初始化成员变量
hour = h;
min = m;
sec = s;
}
*/
#pragma 初始化列表给成员变量初始化
//构造函数 可以用初始化列表 进行初始化
//只需要在参数括号后面加单冒号后面的就是初始化列表
Time (int h = 0,int m = 0,int s = 0):hour(h),min(m),sec(s){
cout << "初始化列表给成员变量初始化" << endl;
}
//重载 构造函数
/*
Time() {
hour = 0;
min = 0;
sec = 0;
cout << "创建对象的时候如果没有参数就默认找到这个无参的Time ()构造方法" << endl;
}
//如果把这个打开注释 main函数里面Time t2;会出现报错时因为上面的构造函数给定默认值了也可以不传参 所以不知道用哪一个
*/
//公开的初始化方法
void init(int h,int m,int s){
hour = h;
min = m;
sec = s;
}
//运行
void run(){
while (1) {
show();
dida();
//代表一个时间
time_t cur = time(0);//0是获取当前系统的时间
//注意理解
while (cur == time(0)) {
//死循环1秒钟
}
}
}
//显示
void show(){
cout << hour << "时" << min << "分" << sec << "秒" << endl;
}
};
//主函数
int main(int argc, const char * argv[])
{
//创建对象 并把参数传进去给构造函数
Time t(15,38,27);
();
//();//这个函数是死循环 下面的代码不会执行
#pragma 现在我希望这样也不报错,那该怎么办?
Time t2;// 一.方法重载 二.有参的构造方法给定参数的默认值
();
#pragma 在创建对象的时候 有参数的话就找到有参的构造函数。无参数的话就默认找到原来的无参的构造函数。
return 0;
}
运行结果如下:
初始化列表给成员变量初始化
15时38分27秒
初始化列表给成员变量初始化
0时0分0秒
0时0分1秒
0时0分2秒
0时0分3秒
Program ended with exit code: 9
利用构造函数初始化成员变量的两种方法:
一.直接在构造函数体中初始化
二.用初始化列表
既然两种方法都可以初始化成员变量,那它们之间到底有什么区别呢??
大多数情况下两种都可以,但是极个别情况必须要用初始化列表。它们的区别在于创建对象那个过程调用的时机。
在方法体里面直接赋值初始化的,是当构造函数已经开始调用了的时候。
而实用初始化列表的,是在构造函数调用前初始化
创建对象的过程
1.开辟内存空间
2.初始化成员变量
3.调用构造方法
也就是说构造方法是最后一个才调用的
这第2步首先得到的是垃圾值,接着再在构造函数体内赋值初始化成员变量。
然而利用初始化列表初始化成员变量的那种方法,它的意思是在第2步的时候告诉编译器:你就别给我垃圾值了,我直接利用初始化列表的值,然后再调用构造方法。
什么情况只能用初始化列表??
class Example{
int x=23451234;//创建对象的时候 这里调用第2步初始化得到的是垃圾值
public:
Example(){
x = 100;//初始化
}
};
/******例如这种情况就必须要使用初始化列表了********/
/*
class Example1{
int x=23451234;//创建对象的时候 这里调用第2步初始化得到的是垃圾值
int& r;//这是引用类型在创建的时候必须给它赋值 如果是这样可能得到垃圾值
public:
Example1(int a){
x = 100;//初始化
r = a;
}
};
*/
class Example1{
int x=23451234;//创建对象的时候 这里调用第2步初始化得到的是垃圾值
int& r;//这是引用类型在创建的时候必须给它赋值
public:
Example1(int a):r(a){ //利用初始化列表给引用初始化
x = 100;//初始化
#pragma 也就是说如果你的成员变量里面有引用类型的,那么必须使用初始化列表,否则等到构造方法一调用那么一切都晚了
}
};
class Example2{
int x=23451234;//创建对象的时候 这里调用第2步初始化得到的是垃圾值
int& r;//这是引用类型在创建的时候必须给它赋值
const int i;
public:
Example2(int a):r(a),i(200){ //利用初始化列表给引用初始化
x = 100;//初始化
//r = a;
// i = 300; //const一旦声明就不能改变它的值了
#pragma 也就是说如果你的成员变量里面有引用类型的,那么必须使用初始化列表,否则等到构造方法一调用那么一切都晚了
//如果成员变量是常量 也需要初始化列表初始化
}
};
总结:
成员变量里面有引用类型的变量 或者 是const常量类型的变量 那就必须要使用初始化列表来初始化成员变量。