生成类对象时,其成员可以用类的构造函数初始化。构造函数是与类同名的成员函数。程序员提供的构造函数在每次生成类对象(实例化)时自动调用。构造函数可以重载.提供初始化类对象的不同方法。数据成员应在类的构造函数中初始化或在生成对象之后设置其数值。
类的数据成员只能在类定义中初始化。
试图声明构造函数的返回类型和返回植是个语法错误。
适当时候(通常都是)应提供一十构速函数,保证每个对象正确地初始化为有意义的值。特别是指针数据类型应初始化为合法指针值或0。
每个修改对象的private数据成员的成员函数(和友元)应确保数据保持一致状态。
声明类对象时,可以在括号中提供初始化值,放在对象名后面和分号前面。这些初始化值作为
参数传递给类的构造函数。稍后会举几个构造函数调用(constructor call)的例子(注意:尽管程序
员不显式调用构造函数,但程序员仍然可以提供数据,作为参数传递给构造函数)。
图6.1time1.cpp中的构造函数将hour、minute和second初始化为0(即军用时间午夜11时)。
构造函数可以包含默认参数。图6.8重新定义Time的构造函数,该函数中每个变量的默认参数为0。通过提供构造函数默认参数,即使在构造函数调用中不提供数值,对象也能利用默认参数初始化为一致状态。程序员提供所有参数默认值(或显式不要求参数)的构造函数也称为默认构造函数(default constnlctor),即可以不用参数而调用的构造函数。一个类只能有一个默认构造函数。
// Fig. 6.8: time2.h
// Declaration of the Time class.
// Member functions are defined in time2.cpp
// preprocessor directives that
// prevent multiple inclusions of header file
#ifndef TIME2_H
#define TIME2_H
// Time abstract data type definition
class Time {
public:
Time( int = 0, int = 0, int = 0 ); // default constructor
void setTime( int, int, int ); // set hour, minute, second
void printMilitary(); // print military time format
void printStandard(); // print standard time format
private:
int hour; // 0 - 23
int minute; // 0 59
int second; // 0 - 59
};
#endif
// Fig. 6.8: time2.cpp
// Member function definitions for Time class.
#include <iostream.h>
#include "time2.h"
// Time constructor initializes each data member to zero.
// Ensures all Time objects start in a consistent state.
Time::Time(int hr,int min,int sec)
{ setTime( hr, min, sec ); }
// Set a new Time value using military time. Perform validity
// checks on the data values. Set invalid values to zero.
void Time::setTime(int h,int m,int s)
{
hour = ( h >= 0 && h < 24 ) ? h : 0;
minute = ( m >0 && m < 60 )? m : 0;
second = ( s >= 0 && s < 60 ) ? s : 0;
}
// Print Time in military format
void Time::printMilitary()
cout << ( hour < 10 ? "O" : "" ) << hour << ":"
<< ( minute < 10 ? "0" : "" ) << minute;
}
// Print Time in standard format
void Time::printStandard()
cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 )
<< ":" <<( minute < 10 ? "0" : "" ) << minute
<< ":" << ( second < 10 ? "0" : "" ) << second
<< ( hour < 12 ? "AM" : "PM" );
}
// Fig. 6.8: fig06_08.cpp
// Demonstrating a default constructor
// function for class Time.
#include< iostream.h>
#include "time2.h"
int main()
{
Time t1, // all arguments defaulted
t2(2), // minute and second defaulted
t3(21, 34), // second defaulted
t4(12, 25, 42), // all values specified
t5(27, 74, 99); // all bad values specified
cout << "Constructed with:\n"
<< "all arguments defaulted:\n ";
t1.printMilitary();
cout << "\n ";
t1.printStandard();
cout << "\nhour specified; minute and second defaulted:"
<< "\n ";
t2.printMilitary{);
cout << "\n ";
t2.printStandard();
cout << "\nhour and minute specified; second defaulted:"
<< "\n ";
t3.printMilitary();
cout << "\n ";
t3.printStandard();
cout << "\nhour, minute, and second specified:"
<< "\n ";
t4.printMilitaryO;
cout << "\n ";
t4.printStandard();
cout << "\nall invalid values specified:"
<< "\n ";
t5.printMilitary();
cout << "\n ";
t5.printStandardO;
cout << endl;
return 0;
}
输出结果:
Constructed with:
all arguments defaulted
00:00
12:00:00 AM
hour specified; minute and second defaulted:
02:00
2:O0:0O AM
hour and minute specified; second defaulted:
21:34
9:34:00 PM
hour, minute, and second specified:
12:25
12:25:42 PM
all invalid values specified:
00:00
12:00:00 AM
图 6.8 构造函数使用默认参数
在这个程序中,构造函数调用成员函数setTime,将数值传人构造函数(或用默认值)保证hour 值取0到13、minute和second值取0到59。如果数值超界,则setTime将其设置为0(使数据成员保证一致状态)。
注意,Time构造函数也可以写成包含与setTime成员函数相同的语句。这样可能会使程序更有效,因为不必另外再调用setTime函数。但让Time构造函数和setTime成员函数使用相同代码会使程序维护更加困难。如果setTime成员函数的实现方法改变,则Time构造函数的实现方法也要相应 改变。Time构造函数直接调用setTime时,setTime成员函数的实现方法只要改变一次即可,这样就 可以在改变实现方法时减少错误。另外,显式声明内联的构造函数或在类定义中定义构造函数也可以提高Time构造函数的性能(后者隐含内联函数定义)。
如果类的成员函数已经提供类的构造函数(或其他成员函数)所需功能的所有部分,则从构造函数(或其他成员函数)调用这个成员函数。这样可以简化代码维护和减少修改代码实现方法时的出错机会。因此就形成了一个一般原则:避免重复代码。
只在头文件内的类定义的函数原型中声明默认函数参数值。
在头文件和成员函数定义中指定同一成员函数的默认初始化值。
图6.8的程序初始化五个Time对象:一个将三个参数指定为默认值,一个指定一个参数,一个指定两个参数.一个指定三个参数,一个指定三个无效参数。每个对象数据成员均显示实例化和初始化之后的内容。
如果类不定义构造函数,则编译器生成默认构造函数。这种构造函数不进行任何初始化,因此生成对象时,不能保证处于一致状态。
类不一定有默认构造函数。