第五讲:构造函数
构造函数
对象的初始化
定义一个普通变量时,可以同时进行初始化,如:
int a=3; 而声明类时,数据成员不能进行初始化: class time { int hour=0; int minute=0; //错误 }; // 因为类不是实体,不占存储空间,无法容纳数据.
如果一个类的所有数据成员都是共用的,在定义对象时(注意:不是声明类时候)可以进行初始化,如:
class time { public: int hour,minute,second; }; time t1={ 13, 30, 20 }; 但在类的声明中,数据成员一般都是私有的,就不能这样初始化,此时就需要一个公有成员函数来完成,而且应该是自动完成--该函数就是构造函数. 构造函数的实质是说明数据成员如何初始化!
- 构造函数的特点和作用
- 定义了创建对象的方法,提供了初始化对象的一种简便手段,构造函数是一个由用户定义的特殊的成员函数.构造函数的说明格式:<类名>([<参数表>]);
- 与其他成员函数的不同之处在于:
- 构造函数必须与类名相同,不能是其它名字
- 构造函数不能有任何返回类型,也没有返回值
- 其功能是对对象进行初始化,一般由一系列赋值语句构成
- 用户不能调用构造函数,而是在定义对象时系统自动调用
- 在类定义时如果没有定义任何构造函数,则编译器自动为类生成一个不带任何参数的默认构造函数,但函体中没有任何语句.如:time(){}
- 构造函数允许重载
无参构造函数举例子
#include <iostream.h> //例4.1
class time
{
private:
int hour, minute, second;
public:
time ( ) //time 类的构造函数
{ hour = 0; minute = 0; second = 0; }
void setTime ( );
void showTime ( )
{ cout << hour <<":"<<minute <<":"<<second <<endl;
}
void time::setTime ( )
{
cout<<"hour = "<<endl;
cin>>hour;
cout<<"minute="<<endl;
cin>>minute;
cout<<"second="<<endl;
cin>>second;
}
void main ( )
{
time t1;
// 定义类对象t1 ,调用构造函数time ( )
t1.setTime( );
t1.showTime ( );
}
思考:无setTime()?无构造函数?
- 带参数的构造函数
- 在上面的构造函数无参类的实例中,每产生一个time对象,其初始值都初始化为0,如果用户初始化时,不想将对象初始置为0而是其他值,就需要用带参数的构造函数来完成
声明构造函数的格式为
构造函数名(类型1 形参1, 类型2 形...);
定义一个对象的一般格式为:
类名 对象名 (实参1, 实参2 … )
- 用参数初始化表对数据成员初始化
- c++提供另一种初始化数据成员的方法:参数初始化表来实现对数据成员的初始化,这种方法不在构造函数体内初始化数据成员,而是在函数首部实现
#include <iostream.h> // 例5.2--2 class box { private: int height, width, length; public: box(int h,int w,int len):height(h),width(w),length(len) { } int volume ( ) { return height * width * length; } }; void main ( ) { box box1 (1,2,3); cout <<"box1的体积=" <<box1.volume( ) << endl; box box2 (4,5,6); cout <<"box2的体积="<<box2.volume( ) << endl; }
示例中的初始化表标识,用形参h的值初始化数据成员height,用w值初始化width,用len值初始化length,这种初始化方法比较简练,可以直接在类体中定义构造函数.
- 构造函数的重载
一个类中,可以有多个构造函数,只要它们的参数表不同,方便同类对象不同初始化的需要.
#include <iostream.h>//例5.3 class circle { private: float ra; public: circle( ); //声明无参数构造函数 circle( float r ): ra (r) { } //定义带参数构造函数 float area ( ) { return ra*ra * 3.14; } }; circle::circle ( ) //定义无参数构造函数 { ra=10.0; } int main ( ) { circle c1(1.0),c2; cout <<"c1的面积=" <<c1.area( ) << endl; cout <<"c2的面积=" <<c2.area( ) << endl; return 0; }
构造函数的重载说明
- 参数表为空的构造函数叫默认构造函数,一个类中只能由一个默认函数,即只有一个构造函数参数表为空
- 定义对象时,如果想用默认构造函数初始化,正确的定义形式为:circle c2;而不是circle c2();
一个类可以定义多个构造函数,一个对象只能用其中一个来初始化.
使用默认参数的构造函数
- 构造函数的参数即可以通过实参传送,也可以指定为某些默认值,当用户不指定实参值时,编译系统便将默认值为形参值
- 在实际应用中,常有一些默认值,如计数器的默认值为0等,如果实际情况不是默认值,则由用户另外指定,采用默认值,可以减少用户的输入量.
#include <iostream.h> //例5.4
class circle
{ private:
float radius;
public:
circle( float r = 1.0 ); // 声明构造函数是指定默认参数
float area ( )
{ return radius * radius * 3.14159; }
};
circle::circle ( float r ) //定义函数时,可不再指定默认参数
{ radius = r; }
void main ( )
{ circle c1 (10.0), c2;
cout <<"c1的面积=" <<c1.area( ) << endl;
cout <<"c2的面积=" <<c2.area( ) << endl;
}
构造函数中使用默认参数的好处:
- 提供建立对象时的多种选择,相当于多个重载的构造函数
- 即使在调用构造时不提供参数也不会出错,因为有默认参数值参与对象初始化
当每一个对象都是相同的初始值时,非常方便,用户不需要输入数据
默认参数值的构造函数使用注意:
- 何处指定默认参数值?构造函数的声明处还是定义处?应该在构造函数的声明处指定默认参数值.因为类的声明在头文件中,用户是看见的,而放在函数的定义处,用户不一定看得见.
- 一个类若定义了全部是默认参数的构造函数后,不能再定义重载的构造函数,否则会出现多义性,系统不知道调用哪一个
circle ( float r=2.3 );
circle ( );
circle ( float );