只能通过成员函数访问对象的成员数据保证了对象状态的合法性,即不可能把对象的成员变量赋值为非法的数据。分析下面的程序。
#include<stdio.h>
#include<string.h>
class Student
{
public:
void setData(char *pName, int se, int ye,int mo, int da, float gr)
{
strcpy(name, pName);
if(se==0 || se==1)
sex = se;
else
sex = 1;
if(ye>0)
year = ye;
else
year = 2000;
if(mo>0 && mo<13)
month = mo;
else
month = 1;
if(da>0 && da<31)
day = da;
else
day = 1;
if(gr>=0 && gr<=100)
grade = gr;
else
grade = 0;
}
void showMessage()
{
printf("姓名:%s\n",name);
printf("性别:%s\n",sex==1 ? "男" : "女");
printf("出生日期:%d年%d月%d日\n",year, month, day);
printf("英语成绩:%.1f\n", grade);
}
private:
char name[10];
int sex; //1为男0为女
int year;
int month;
int day;
float grade;//英语成绩
};
int main()
{
Studentzhang3;
zhang3.showMessage();
return0;
}
程序的执行结果为:
姓名:烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫?
性别:女
出生日期:-858993460年-858993460月-858993460日
英语成绩:-107374176.0
由程序的输出结果可知,对象zhang3并没有处于合法的状态。无论怎样使用对象(即使用非法的数据给对象赋值),对象都会处于合法的状态,但在对象“产生”后至“使用”前一起处于“非法”的状态。如何保证对象一产生就处于合法的状态呢?
定义对象时用合法的数据给对象赋值。
类中有一种特殊的成员函数,即构造函数。定义对象时,构造函数会被自动调用,因此,可以通过构造函数保证对象的合法状态。切记,只要有对象产生,必定会有构造函数执行。上面的程序中,也就是说,编译系统帮忙自动为程序员调用了构造函数。构造函数应该什么样子呢?
名字必须特殊,类属于用户定义数据类型,如果程序员可以随意为构造函数命名,编译系统就不可能找到构造函数,也就不可能替程序员调用构造函数了。构造函数就是与类名相同的函数。
构造函数没有返回值,这很自然,编译系统帮忙调用的函数要返回值有什么用?构造函数不用void表示没有返回值,直接就是函数名。可以用下面的代码定义一个类Student构造函数。
Student(){}
疑问在于示例程序中Student类并没有定义构造函数,对象定义语句Student zhang3;执行时,构造函数怎样自动执行呢?
编译系统会为没有定义构造函数的类定义一个“默认”构造函数,不过编译系统定义的构造函数什么也不做,如上面的构造函数所示。
上面程序中在对象生成时,虽然执行了编译系统定义的构造函数,但生成后对象还是处于非法的状态,因此需要程序员为类定义一个“合适”的构造函数。修改程序中类的定义如下:
class Student
{
public:
Student()
{
strcpy(name, "NoName");
sex = 1;
year = month = day = 1;
grade = 0;
}
......
};
修改后程序的运行结果如下:
姓名:NoName
性别:男
出生日期:1年1月1日
英语成绩:0.0
构造函数可以重载。可以再定义一个构造函数,
Student(char *pName, int se, int ye, int mo,int da, float gr)
{
setData(pName,se, ye, mo, da, gr);
}
则可以用语句Student li4("Li4", 1, 2000, 10, 10, 95);定义一个名为li4的对象。
有了构造函数,程序员可以保证对象一产生就处于合法的状态,而且对象也可以初始化了。
下面的程序会出现语法错误。
#include<stdio.h>
#include<string.h>
class Student
{
public:
Student(char *pName, int se, int ye, intmo, int da, float gr)
{
setData(pName, se, ye, mo, da,gr);
}
void setData(char *pName, int se, int ye,int mo, int da, float gr)
{
strcpy(name, pName);
if(se==0 || se==1)
sex = se;
else
sex = 1;
if(ye>0)
year = ye;
else
year = 2000;
if(mo>0 && mo<13)
month = mo;
else
month = 1;
if(da>0 && da<31)
day = da;
else
day = 1;
if(gr>=0 && gr<=100)
grade = gr;
else
grade= 0;
}
void showMessage()
{
printf("姓名:%s\n",name);
printf("性别:%s\n",sex==1 ? "男" : "女");
printf("出生日期:%d年%d月%d日\n",year, month, day);
printf("英语成绩:%.1f\n", grade);
}
private:
char name[10];
int sex; //1为男0为女
int year;
int month;
int day;
float grade;//英语成绩
};
int main()
{
Studentzhang3;
zhang3.showMessage();
Student li4("Li4", 1, 2000, 10,10, 95);
li4.showMessage();
return 0;
}
语句Student zhang3;执行时需执行默认构造函数,而类中却没有(参数为空)默认构造函数。当类中有了构造函数后,编译系统就不会为类自动生成默认构造函数了。没有了默认构造函数,类似Student zhang3;的语句就无法执行了,所以就出现了语法错误。
解决方案有两个。一是定义一个默认构造函数。二是为构造函数的每个参数设置缺省值。如Student(char *pName="NoName", int se=1, int ye=1, intmo=1, int da=1, float gr=0)
{
setData(pName, se, ye, mo, da,gr);
}