一个类的对象作为另一个类的数据成员时如何构造函数

来源:互联网 发布:2018年四川省大数据 编辑:程序博客网 时间:2024/05/18 09:20
  一个类的对象作为另一个类的数据成员。
 
     一个类中的数据成员除了可以是int, char, float等这些基本的数据类型外,还可以是某一个类的一个对象。用子对象创建新类。
 
     在C++中,当把一个类的对象作为新类的数据员时,则新类的定义格式可表示为:
 
class X
 
{ 类名1  成员名1;
 
  类名2  成员名2;
 
  ……
 
  类名n  成员名n;
 
  ……//其它成员
 
};
 
(3)如果一个类A的对象作为另一个类B的数据成员,则在类B的对象创建过程中,调用其构造函数的过程中,数据成员(类A的对象)会自动调用类A的构造函数。
 
但应注意:如果类A的构造函数为有参函数时,则在程序中必须在类B的构造函数的括号后面加一“:”和被调用的类A的构造函数,且调用类A的构造函数时的实参值必须来自类B的形参表中的形参。这种方法称为初始化表的方式调用构造函数。如:以上面定义的类X为例,在对类X的对象进行初始化时,必须首先初始化其中的子对象,即必须首先调用这些子对象的构造函数。因此,类X的构造函数的定义格式应为:
 
X::X(参数表0):成员1(参数表1),成员2(参数表2),…,成员n(参数表n)
 
{ ……}
 
其中,参数表1提供初始化成员1所需的参数,参数表2提供初始化成员2所需的参数,依此类推。并且这几个参数表的中的参数均来自参数表0,另外,初始化X的非对象成员所需的参数,也由参数表0提供。
 
在构造新类的对象过程中,系统首先调用其子对象的构造函数,初始化子对象;然后才执行类X自己的构造函数,初始化类中的非对象成员。对于同一类中的不同子对象,系统按照它们在类中的说明顺序调用相应的构造函数进行初始化,而不是按照初始化表的顺序。












以下定义了三个Student、Teacher和Tourpair,其中Student类的对象和Teacher类的对象作为了Tourpair的数据成员,观察对象的构造过程和构造函数被执行的顺序。
 
#include <iostream.h>
 
class Student
 
{ public: 


   Student()
 
    { cout<<”construct student.\n”;
 
       semeshours=100;
 
       gpa=3.5;   }   


protected:
 
     int semeshours;
 
     float gpa;
 
};
 
class Teacher
 
{ public:
 
     Teacher()
 
   { cout<<”construct Teacher.\n”; 


    }
 
 };
 
class Tourpair
 
{public:
 
     Tourpair()
 
     {cout<<”construct tourpair.\n”;
 
      nomeeting=0;  }
 
  protected:
 
      Student student;
 
      Teacher teacher;
 
      int nomeeting;
 
 };
 
void main()
 
{Tourpair tp;
 
cout<<”back in main.\n”; }
 
其执行结果是:
 
   construct student.
 
   construct teacher.
 
   construct tourpair.
 
   back in main.
 
      由此可见:主函数main()运行开始时,遇到要创建Tourpair类的对象,于是调用其构造函数Tourpair(),该构造启动时,首先分配对象空间(包含一个Student对
 
象、一个Teacher对象和一个int型数据),然后根据其在类中声明的对象成员的次序依次调用其构造函数。即先调用Student()构造函数,后调用Teacher()构造函数,最后才执行它自己的构造函数的函数体。
 
     由于上例中Tourpair类的数据成员student和teacher的构造函数都是无参函数,所以系统在构造student和teacher对象时会自动调用各自的构造函数Student()和Teacher(),而不需要用初始化表的方式去调用。
 
【例3-7】试分析以下程序的执行结果:
 
#include <iostream.h>
 
#include <string.h>
 
class Student
 
{ public:
 
   Student(char *pName="No name")
 
      { cout<<"构造新同学:"<<pName<<endl;
 
         strncpy(name,pName,sizeof(name)); char * strncpy(char *dest, char *src, size_t n); 将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到NULL才停止复制,而是等凑够n个字符才开始复制),返回指向dest的指针。              C语言中判断数据类型长度符
 
         name[sizeof(name)-1]='\0';  


        }
 
 Student(Student &s)
 
      { cout<<"构造copy of "<<s.name<<endl;
 
         strcpy(name, " copy of ");  extern char *strcpy(char *dest,char *src);    把src所指由NULL结束的字符串复制到dest所指的数组中
 
         strcat(name,s.name);    extern char *strcat(char *dest,char *src);          把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
 
         }
 
~Student()
 
 { cout<<"析构 "<<name<<endl; }
 
    protected:
 
    char name[40];  };
 
class Tutor
 
{ public: 


       Tutor(Student &s):student(s)//此为初始化表,调用
 
                                                     //Student的拷贝构造函数
 
       { cout<<"构造指导教师 \n";  }
 
   protected:
 
        Student student;
 
 };
 
void main()
 
{  Student st1;   //此处调用Student的构造函数Student(char  


           *pName="No name")
 
   Student st2("zhang"); //同上
 
   Tutor tutor(st2); //此处调用Tutor的构造函数Tutor(Student &s)
 
   //在构造tutor对象的过程中,用初始化表调用
 
   //Student类的拷贝构造函数Student(Student &s)
 
}
 
执行结果如下:
 
构造新同学:No name
 
构造新同学:zhang
 
构造copy of zhang
 
构造指导教师
 
析构  copy of zhang
 
析构 zhang
 
析构 No name
 
3.2.7 利用初始化表对常量数据成员或引用成员提供初值
 
     如前所述,构造函数可对对象的数据成员进行初始化,但若数据成员为常量成员或引用成员时,就有所不同,如:
 
class Sillyclass
 
{ public :
 
Sillyclass()   // 此构造函数对成员ten和refi的初始化错误。
 
    { ten=10;
 
       refi=i; }
 
protected:
 
    const int ten;   //常量数据成员ten
 
    int &refi;         //引用refi
 
};
 
说明:
 
1. 造成以上错误的原因是在Sillyclass类的构造函数进入之后(开始执行其函数体时),对象结构已经建立,数据成员ten和refi已存在,而其数据成员ten为const,而refi为引用,所以在构造函数体内不能再对其指派新的值。
 
2. 解决以上问题的方法是利用初始化表:在构造函数的括号后面加一“:”和初始化表,初始化表的格式是:
 
数据成员名(值),如果有多个时,需要用逗号隔开。
 
【例3-8】 类employee中包括私有数据成员x, 和2个公有函数成员example、show。程序中使用初始化表是x(215)。
 
# include <windows.h>
 
# include <iostream.h>
 
// 定义类 employee
 
class  employee
 
{private:
 
     const int x;
 
  public:
 
     employee ();
 
     void show(); 


 };
 
// employee的类外定义
 
employee :: employee () : x (215)   // 初始化表
 
{                   }
 
// show()的定义。
 
void employee :: show()
 
{  cout << "\n    x的值是:"<< x << endl; }
 
// 主函数
 
void main()
 
{   //生成对象并为x赋予初始值
 
   employee obj;
 
     //调用show显示x的值
 
   obj.show();
 
}
原创粉丝点击