现在我们来看构造函数中冒号初始化和函数初始化的问题,类构造函数的作用是创建一个类的对象时,调用它来构造这个类对象的数据成员,一要给出此数据成员分 配内存空间,二是要给函数数据成员初始化,构造数据成员是按数据成员在类中声明的顺序进行构造。
冒号初始化与函数体初始化的区别在于:
冒号初始化是给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式),那么 分配了内存空间后在进入函数体之前给数据成员赋值,就是说初始化这个数据成员此时函数体还未执行。
对于在函数中初始化,是在所有的数据成员被分配内存空间后才进行的。
这样是有好处的,有的数据成员需要在构造函数调入之后函数体执行之前就进行初始化如引用数据成员,常量数据成员和对象数据成员,看下面的一段程序:
class student
{public :
student ()
.
.
.
protected:
const int a;
int &b;
}
student ::student (int i,int j)
{
a=i;
b=j;
}
在Student类中有两个数据成员,一个是常量数据成员,一个是引用数据成员,并且在构造函数中初始化了这两个数据成员,但是这并不能通过编译,因为常 量初始化时必须赋值,它的值是不能再改变的,与常量一样引用初始化也需要赋值,定义了引用后,它就和引用的目标维系在了一起,也是不能再被赋值的。所以C
++":"后初始化的机制,使引用和常量数据成员变为可能的,Student类的构造函数应为:
student ::student(int i,int j):a(i),b(j){}
在下面的程序:
class teach
{
public :
teach(char *p="name",int a=0)
.
.
.
protected:
char name[30];
int age;
}
teach ::teach(char*p,int a)
{
strcopy(name ,p);
age=a;
cout>>name>>endl;
}
class student
{
public:
student (char *p="name");
.
.
.
protected;
char name[30];
teach teacher;
};
student::student(char *p)
{
strcopy(name,p);
cont>>name>>endl;
}
在上面的程序中通不过编译,编译系统会告诉你teacher这个类对象缺默认构造函数,因为在teach 类中没有定义默认的构造函数。那么带参数的构造函数怎么进行构造呢?通过我们前面提到的冒号赋值。那它的构造函数应该是:
student::student(char *p,char *pl,int ag):teacher(pl,ag)
{
strcopy(name,p);
cont>>name>>endl;
}
就是说在没有默认构造函数的时候,如果一个类对象是另一个类的数据成员,那么初始化这个数 据成员,就应该放到冒号后面。这样可以带参数。在类的定义中,如:
protected;
char name[30];
teach teacher
类对象是不能带参数的,因为它只是声明。
所以在C++中就增加了这种机制,这是面向对象编程所必须的。不知道我讲明白没有。如不明白请查阅有关资料。