- 构造函数
定义:是一个特殊的成员函数,名字与类名相同,创建类类型对象时,由编译器自动调用,在对象的生命周期内只
且值调用一次,以保证每个数据成员都有一个合适的初始值。
特征:1. 函数名与类名相同
2.无返回值
3.在对象构造(对象实例化)时系统会自动调用相应的构造函数
4.构造函数可以重载
5.构造函数可以在类中定义,也可以在类外定义
6.构造函数可以重载,即一个类中可以定义多个参数个数或参数类型不同的构造函数
7.类中没有显式给出构造函数,系统会自动生成一个构造函数(如果不实现其他功能,编译器会优化构造函
数,也就是找不到对应的汇编代码,所以一般要自己给出构造函数)
8.无参的构造函数和带有缺省值的构造函数都认为是缺省构造函数,并且缺省的构造函数只能有一个
注意:在构建对象时,如果它是无参的构造函数,则不需要在对象后面加上括号
例如:
#include<iostream>
using namespace std;
class Date
{
public:
<span style="color:#ff0000;">Date()
{</span>
cout << "Date()" << endl;
//code
<span style="color:#ff0000;">}</span>
private:
int value;
};
int main()
{
<span style="color:#ff0000;">Date d1();//打断点单步运行后直接跳过,断点往下走了。而且没有打印 </span><strong> Date() </strong><span style="color:#ff0000;">所以这样就d1没有定义出来</span>
return 0;
}
提示警告信息: warning C4930: “Date d1(void)”: 未调用原型函数(是否是有意用变量定义的?)
构造函数作用:
1.构建对象 //创建对象时都会运行构造函数
2.初始化对象 //构造函数的初始化列表
3.类型转换 // 将参数对应的类型转换为该类类型
构造函数的分类
//无参的构造函数
//只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来
class Date
{
public:
Date()
{
cout << "Date()" << endl;
//code
}
private:
int value;
};
//一般构造函数(重载构造函数)
//般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是满足重载的条件
//重载函数的条件:函数名相同、同一个作用域、参数列表不同(形参个数,类型,顺序)
class Date
{
public:
Date(int _year) //重载函数1
{
cout << "Date(1)" << endl;
//code
}
Date(int year,double time) //重载函数2
{
cout << "Date(2)" << endl;
//code
}
private:
int _year;
double time;
};
//复制构造函数(也称拷贝构造函数)
//复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在
对象的数据成员的值复制一份到新创建的对象中
//若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数
Complex(const Complex & c)
{
// 将对象c中的数据成员值复制过来
m_real = c.m_real;
m_imag = c.m_imag;
}
//类型转换构造函数根据一个指定的类型的对象创建一个本类的对象
//这个其实就是一般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为
该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使用explicit来限制这种转换。
explicit用法注意:用explicit修饰构造函数,抑制由构造函数定义的隐式转换,explicit关键字类内部的构建声明上,在类的定义体外部的定义上不再重复。
// 下面将根据一个double类型的对象创建了一个Complex对象
Complex(double r)
{
m_real = r;
m_imag = 0.0;
}
初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个数据成员后面跟一个放在园括
号中的初始化式。
class Date
{
public:
Date(int year = 2016, int month = 6, int day = 4)
<strong><span style="color:#ff0000;">:_year(year)
,_month(month)
,_day(day)</span></strong>
{
cout << "Date()" << endl;
//code
}
private:
int _year;
int _month;
int _day;
};
初始化顺序:
1.每个成员在初始化列表中只能出现一次
2.初始化列表仅用于初始化数据成员,并不指定这些数据成员的初始化顺序,数据成员在类中定义顺序就是
在参数列表中的初始化顺序
3.尽量避免使用成员初始化成员,成员的初始化顺序最好和成员的定义顺序保持一致
- 拷贝构造函数
定义:只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数称为拷贝构造函数。
拷贝构造函数是特殊的构造函数,创建对象时使用已存在的同类对象来进行初始化,由编译器自动调用。
class CDate
{
public:
CDate()
{}
CDate( const int year, const int month, const int day)
{
_iYear = year;
_iMonth = month;
_iDay = day;
}
<strong><span style="color:#ff0000;"> CDate( const CDate& date)
{
_iYear = date._iYear;
_iMonth = date._iMonth;
_iDay = date._iDay;
}</span></strong>
private:
int _iYear;
int _iMonth;
int _iDay;
};
特征:
1.它是构造函数的重载
2.参数必须使用同类型对象的引用传递
3.如果没有显式定义,系统会自动合成一个默认的拷贝构造函数。默认的拷贝构造函数会依次拷贝类的数据成
员完成初始化
使用场景;
对象实例化
Date d1(2016,6,4);
Date d2(d1);
传值方式作为函数参数(一般形参加const)
void FunTest(const CDate date)
{
}
传值方式作为函数返回值
CDate FunTest()
{
CDate date;
return date;
}