13.1.4 构造函数
构造函数就是构造类的实例时,系统自动调用的成员函数。当一个对象被创建时,它是否能够被正确地初始化,在C++(www.cppentry.com)中是通过构造函数来解决问题的。每当对象被声明或者在堆栈中被分配时,构造函数即被调用。构造函数是一种特殊的类成员,其函数名和类名相同,声明格式如下:
- <函数名>(<参数列表>);
【示例13-6】 演示构造函数的使用方法。
- class student
- {
- private:
- int id; //学号
- float chinese,english,math; //语文、英语、数学三门课程成绩
- public:
- //构造函数
- student();
- //构造函数,设置学号,姓名,三门课程成绩
- student(int m_id,float m_chinese,float m_english,float m_math);
- void show();
- }
- //无参数构造函数的定义,初始化各属性
- student::student()
- {
- id=0;
- chinese=english=math=0;
- }
- //有参数构造函数的定义,初始化各属性
- student(int m_id,char * m_name,float m_chinese,float m_english,float m_math)
- {
- id=m_id;
- chinese=m_chinese;
- english=m_english;
- math=m_math;
- }
- student::show()
- {
- cout<<id<<endl;
- cout<<chinese<<endl;
- cout<<english<<endl;
- cout<<math<<endl;
- }
分析:该示例定义了两个构造函数,第一个构造函数不带参数,所有属性都被初始化为0。第二个构造函数带参数,用传入的参数来初始化类的属性。构造函数的个数没有限制,可以根据需要定义多个,每个都针对不同的初始化情况。
在定义和使用构造函数时要注意以下几个问题:
构造函数的名字必须与类名相同,否则编译程序将把它作为一般的成员函数来处理;
构造函数没有返回值,在声明和定义构造函数时是不能说明它的类型的;
构造函数的功能是对对象进行初始化,因此在构造函数中只能对属性做初始化,这些属性一般为私有成员;
构造函数不能像其他方法一样被显式地调用。
下面通过示例13-6中的类student,来说明构造函数使用上应该注意的几个问题。
1.构造函数的调用
【示例13-7】 演示类student的构造函数调用的方法。
- int main()
- {
- student s1; //定义类的实例,不显式初始化
- student s2(1,60,70,80); //定义类的实例,显式初始化
- //s2.student(1,60,70,80); //不能显式调用构造函数
- s1.show();
- s2.show();
- return 0;
- }
程序运行结果如下:
- 0
- 0
- 0
- 0
- 1
- 60
- 70
- 80
分析:从输出结果看,在main函数中,构造函数没有被显式调用,而在初始化对象时自动调用。其中,s1调用的构造函数是不带参数的student(),s2调用的则是带参数的构造函数。代码中注释掉的语句是错误的,构造函数不能被显式调用。
2.拷贝构造函数
拷贝构造函数是一种特殊的构造函数,即复制另一个对象的构造函数。一般在下述3种情况下会用到拷贝构造函数:
用一个类对象显式初始化另一个类对象;
把类对象作为实参传递给函数;
将类对象作为函数的返回值时。
在这些情况下,系统就会自动调用拷贝构造函数,将参数代表的对象中的属性逐个拷贝到新创建的对象中。拷贝构造函数有两种形式:系统默认形式和自定义形式。
【示例13-8】 演示系统默认形式的使用方法。
- int main()
- {
- student s1(1,80,90,85); //显式初始化
- s1.show();
- student s2(s1); //拷贝构造
- s2.show();
- return 0;
- }
程序运行结果如下:
- 1
- 80
- 90
- 85
- 1
- 80
- 90
- 85
分析:对象s1在定义时,调用了带参数的构造函数。在定义对象s2时,采用了student s2(s1)的形式,此时调用的是系统默认的拷贝构造函数。拷贝构造函数将s1对象的属性都复制给了s2对象相应的属性中。因此,s2对象的属性值与s1对象的属性值相同。
自定义形式的构造函数的声明方式如下:
- <类名>::<函数名>(<类名>&<参数名>)
- {
- //函数体
- }
【示例13-9】 给示例13-6增加一个具有自定义拷贝构造功能的构造函数,演示自定义形式的使用方法。
- //自定义拷贝构造函数在类体内的声明方式
- //student(const student &s);
- //它的定义如下所示
- inline student::student(const student &s)
- {
- id=s.id;
- name=s.name;
- chinese=s.chinese;
- english=s.english;
- math=s.math;
- }
- void main()
- {
- student s1(1,80,90,85); //显式初始化
- s1.show();
- student s2(s1); //调用拷贝构造函数
- s2.show();
- }
程序运行结果如下:
- 1
- 80
- 90
- 85
- 1
- 80
- 90
- 85
分析:当定义s2时,采用student s2(s1)的形式,调用了用户自定义的拷贝构造函数。实际上,拷贝构造函数就是用类作为构造函数的参数。
提示:如果类不定义构造函数,则编译器生成默认构造函数。这种构造函数不进行任何初始化,因此生成对象时,不能保证处于一致状态。
| 回书目 上一节 下一节 |