C++构造函数的定义和使用
构造函数是类的特殊成员函数,用于初始化对象。构造函数在创建对象时由编译器自动调用。
C++ 中的每个类至少要有一个构造函数,如果类中没有定义构造函数,系统会提供一个默认的无参构造函数,默认的无参构造函数体也为空,不具有实际的初始化意义。因此,在 C++ 程序中要显示定义构造函数。
本文将针对构造函数的定义与具体用法进行详细讲解。
注意:如果在类中提供了自定义构造函数,编译器便不再提供默认构造函数。自定义构造函数时,可以定义无参构造函数,也可以定义有参构造函数,下面分别进行讲解。
【示例1】通过案例演示无参构造函数的定义与调用。C++ 代码如下:
本例对象 clock 的初始化时间为 00:00:00,因为创建 clock 对象调用的是无参构造函数,无参构造函数将时、分、秒都初始化为 0。
【示例2】修改【示例1】,将无参构造函数修改为有参构造函数,以演示有参构造函数的定义与使用。C++ 代码如下:
注意:在实现构造函数时,除了在函数体中初始化成员变量,还可以通过
【示例3】Clock 类可以定义多个构造函数,示例代码如下所示:
修改【示例2】,在 Clock 类中定义重载构造函数,并且其中一个构造函数具有默认参数,在创建对象时,构造函数调用会产生二义性。
【示例4】C++ 程序代码如下:
含有成员对象的类的定义格式如下所示:
例如,上述格式中,类 B 包含一个类 A 对象作为成员变量,在创建类 B 对象时,先执行类 A 的构造函数,将类 A 对象创建出来,再执行类 B 的构造函数,创建类 B 对象。如果类 A 构造函数有参数,其参数要从类 B 的构造函数中传入,且必须以
在类中包含对象成员,能够真实地描述客观事物之间的包含关系,比如描述学生信息的类,类中的成员除了姓名、学号属性,还包含出生日期。
在定义学生类的时候,可以先定义一个描述年、月、日的出生日期类,再定义学生类,将出生日期类的对象作为学生类的成员变量。
【示例5】通过案例演示含有成员对象的类的构造函数的定义与调用。C++ 代码如下:
由运行结果可知,学生对象成功创建且显示出了学生信息。创建对象 stu 时,先调用 Birth 类构造函数,之后才调用 Student 类构造函数。
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
C++ 中的每个类至少要有一个构造函数,如果类中没有定义构造函数,系统会提供一个默认的无参构造函数,默认的无参构造函数体也为空,不具有实际的初始化意义。因此,在 C++ 程序中要显示定义构造函数。
本文将针对构造函数的定义与具体用法进行详细讲解。
自定义构造函数
构造函数是类的特殊成员函数,C++ 编译器严格规定了构造函数的接口形式,其定义格式如下所示:
class 类名
{
权限控制符:
构造函数名(参数列表)
{
函数体
}
... //其他成员
};
- 构造函数名必须与类名相同。
- 构造函数名的前面不需要设置返回值类型。
- 构造函数中无返回值,不能使用 return 返回。
- 构造函数的成员权限控制符一般设置为 public。
注意:如果在类中提供了自定义构造函数,编译器便不再提供默认构造函数。自定义构造函数时,可以定义无参构造函数,也可以定义有参构造函数,下面分别进行讲解。
1) 自定义无参构造函数
自定义无参构造函数时,可以在函数内部直接给成员变量赋值。【示例1】通过案例演示无参构造函数的定义与调用。C++ 代码如下:
#include<iostream> #include<iomanip> using namespace std; class Clock //定义时钟类Clock { public: Clock(); //声明无参构造函数 void showTime(); //声明显示时间的成员函数 private: int _hour; //声明表示小时的成员变量 int _min; //声明表示分钟的成员变量 int _sec; //声明表示秒的成员变量 }; Clock::Clock() //类外实现无参构造函数 { _hour=0; //初始化过程,将成员变量初始化为0 _min=0; _sec=0; } void Clock::showTime() //类外实现成员函数 { cout<<setw(2)<<setfill('0')<<_hour<<":" <<setw(2)<<setfill('0')<<_min<<":" <<setw(2)<<setfill('0')<<_sec<<endl; } int main() { Clock clock; //创建对象clock cout<<"clock:"; clock.showTime(); //通过对象调用成员函数showTime()显示时间 return 0; }运行结果:
clock:00:00:00
示例分析:- 第 7 行代码声明了一个无参构造函数;
- 第 14~19 行代码在类外实现构造函数,在构造函数体中直接将初始值赋给成员变量;
- 第 28~30 行代码在 main() 函数中创建了对象 clock,并通过对象调用 showTime() 成员函数显示初始化时间。
本例对象 clock 的初始化时间为 00:00:00,因为创建 clock 对象调用的是无参构造函数,无参构造函数将时、分、秒都初始化为 0。
2) 自定义有参构造函数
如果希望在创建对象时提供有效的初始值,可以通过定义有参构造函数实现。【示例2】修改【示例1】,将无参构造函数修改为有参构造函数,以演示有参构造函数的定义与使用。C++ 代码如下:
#include<iostream> #include<iomanip> using namespace std; class Clock //定义时钟类Clock { public: Clock(int hour, int min, int sec); //声明有参构造函数 void showTime(); //用于显示时间的成员函数 private: int _hour; //声明表示小时的成员变量 int _min; //声明表示分钟的成员变量 int _sec; //声明表示秒的成员变量 }; Clock::Clock(int hour, int min, int sec) //类外实现有参构造函数 { _hour=hour; //初始化过程,将初始值直接赋值给成员变量 _min=min; _sec=sec; } void Clock::showTime() //类外实现成员函数 { cout<<setw(2)<<setfill('0')<<_hour<<":" <<setw(2)<<setfill('0')<<_min<<":" <<setw(2)<<setfill('0')<<_sec<<endl; } int main() { Clock clock1(10,20,30); //创建对象clock1,传入初始值 cout<<"clock1:"; clock1.showTime(); //通过对象调用成员函数showTime()显示时间 Clock clock2(22,16,12); //创建对象clock2,传入初始值 cout<<"clock2:"; clock2.showTime(); //通过对象调用成员函数showTime()显示时间 return 0; }运行结果:
clock1:10:20:30
clock2:22:16:12
- 第 7 行代码声明了有参构造函数;
- 第 14~19 行代码在类外实现有参构造函数,将参数赋值给成员变量,在创建对象时调用有参构造函数,用户可以传入初始值(参数)完成对象初始化;
- 第 28~33 行代码,创建了两个 Clock 对象 clock1 和 clock2,这两个对象在创建时,传入了不同的参数,因此各个对象调用成员函数 showTime() 显示的初始化时间是不一样的。
注意:在实现构造函数时,除了在函数体中初始化成员变量,还可以通过
:
运算符在构造函数后面初始化成员变量,这种方式称为列表初始化,其格式如下所示:
类::构造函数(参数列表): 成员变量1(参数1), 成员变量2(参数2),…, 成员变量n(参数n)
{
构造函数体
}
Clock::Clock(int hour, int min, int sec):_hour(hour),_min(min),_sec(sec)
{
//...
}
重载构造函数
在 C++ 中,构造函数允许重载。【示例3】Clock 类可以定义多个构造函数,示例代码如下所示:
class Clock //定义时钟类Clock { public: //构造函数重载 Clock(); Clock(int hour); Clock(int hour, int min); Clock(int hour, int min, int sec); void showTime(); //声明显示时间的成员函数 private: int _hour; //声明表示小时的成员变量 int _min; //声明表示分钟的成员变量 int _sec; //声明表示秒的成员变量 };当定义具有默认参数的重载构造函数时,要防止调用的二义性。
修改【示例2】,在 Clock 类中定义重载构造函数,并且其中一个构造函数具有默认参数,在创建对象时,构造函数调用会产生二义性。
【示例4】C++ 程序代码如下:
#include<iostream> #include<iomanip> using namespace std; class Clock //定义时钟类Clock { public: //声明重载构造函数 Clock(int hour, int min); Clock(int hour, int min, int sec=0); void showTime(); //声明显示时间的成员函数 private: int _hour; //声明表示小时的成员变量 int _min; //声明表示分钟的成员变量 int _sec; //声明表示秒的成员变量 }; Clock::Clock(int hour, int min):_hour(hour),_min(min) { cout<<"调用两个参数的构造函数"<<endl; _sec=10; } Clock::Clock(int hour, int min, int sec=0) //类外实现构造函数 { cout<<"调用三个参数的构造函数"<<endl; _hour=hour; _min=min _sec=sec; } void Clock::showTime() //类外实现成员函数showTime() { cout<<setw(2)<<setfill('0')<<_hour<<":" <<setw(2)<<setfill('0')<<_min<<":" <<setw(2)<<setfill('0')<<_sec<<endl; } int main() { Clock clock(8,0); //创建对象clock,传入初始值 cout<<"clock:"; clock.showTime(); //通过对象调用成员函数显示时间 return 0; }本例运行时编译器会报错:
“Clock::Clock”:对重载函数的调用不明确
“Clock::Clock”:重定义默认参数:参数1
有多个构造函数“Clock::Clock”的实例与参数列表匹配
- 第 8 行代码声明了一个构造函数,该构造函数有两个参数;
- 第 9 行代码声明了一个构造函数,该构造函数有三个参数,且第三个参数有默认值;
- 第 16~27 行代码,在类外实现了这两个构造函数;
- 第 36 行代码,在main() 函数中创建一个对象 clock,传入两个参数,编译器无法确认调用的是第 8 行的构造函数还是第 9 行的构造函数,因此无法通过编译。
含有成员对象的类的构造函数
C++ 允许将一个对象作为另一个类的成员变量,即类中的成员变量可以是其他类的对象,这样的成员变量称为类的子对象或成员对象。含有成员对象的类的定义格式如下所示:
class B
{
A a; //对象a作为类B的成员变量
... //其他成员
}
例如,上述格式中,类 B 包含一个类 A 对象作为成员变量,在创建类 B 对象时,先执行类 A 的构造函数,将类 A 对象创建出来,再执行类 B 的构造函数,创建类 B 对象。如果类 A 构造函数有参数,其参数要从类 B 的构造函数中传入,且必须以
:
运算符初始化类 A 对象。在类中包含对象成员,能够真实地描述客观事物之间的包含关系,比如描述学生信息的类,类中的成员除了姓名、学号属性,还包含出生日期。
在定义学生类的时候,可以先定义一个描述年、月、日的出生日期类,再定义学生类,将出生日期类的对象作为学生类的成员变量。
【示例5】通过案例演示含有成员对象的类的构造函数的定义与调用。C++ 代码如下:
#include<iostream> using namespace std; class Birth //定义出生日期类Birth { public: Birth(int year,int month, int day); //构造函数 void show(); //声明成员函数show()显示日期 private: int _year; int _month; int _day; }; //类外实现构造函数 Birth::Birth(int year, int month, int day) :_year(year),_month(month),_day(day) { cout<<"Birth类构造函数"<<endl; } //类外实现show()函数 void Birth::show() { cout<<"出生日期:"<<_year<<"-"<<_month<<"-"<<_day<<endl; } class Student //定义学生类Student { public: //构造函数 Student(string name, int id, int year, int month, int day); void show(); private: string _name; int _id; Birth birth; }; //类外实现构造函数 Student::Student(string name, int id, int year, int month, int day) :birth(year,month,day) { cout<<"Student类构造函数"<<endl; _name=name; _id=id; } //类外实现show()函数 void Student::show() { cout<<"姓名:"<<_name<<endl; cout<<"学号:"<<_id<<endl; birth.show(); } int main() { Student stu("lili",10002,2000,1,1); //创建学生对象stu stu.show(); //显示学生信息 return 0; }运行结果:
Birth类构造函数
Student类构造函数
姓名:www.weixueyuan.net
学号:10002
出生日期:2012-1-1
- 第 3~12 行代码定义了出生日期类 Birth,该类有 3 个成员变量,分别是 _year、_month、_day,并且定义了有参数的构造函数;
- 第 24~34 行代码定义了学生类 Student,该类有 3 个成员变量,分别是 _name、_id、birth,其中 birth 是类 Birth 的对象。此外,Student 类还定义了一个构造函数。由于成员对象 birth 的构造函数有 3 个参数,这 3 个参数要从类 Student 的构造函数中获取,因此 Student 类的构造函数共有 5 个参数;
-
第 36~42 行代码用于实现 Student 类的构造函数,birth 成员对象必须通过
:
运算符在 Student 构造函数后面初始化,无法在 Student 构造函数体中赋值; - 第 52~53 行代码,在 main() 函数中创建 Student 类对象 stu,并通过对象 stu 调用成员函数 show() 显示学生信息。
由运行结果可知,学生对象成功创建且显示出了学生信息。创建对象 stu 时,先调用 Birth 类构造函数,之后才调用 Student 类构造函数。
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。