C++中派生类通过基类方法访问基类私有成员
派生类不能直接访问基类的私有成员,而必须通过基类方法进行访问。例如,RatedPlayer构造函数不能直接设置继承的成员(firstname、lastname和 hasTable),而必须使用基类的公有方法来访问私有的基类成员。具体地说,派生类构造函数必须使用基类构造函数。
创建派生类对象时,程序首先创建基类对象。从概念上说,这意味着基类对象应当在程序进入派生类构造函数之前被创建。C++使用成员初始化列表语法来完成这种工作。例如,下面是第一个RatedPlayer 构造函数的代码:
Ratedplayer::RatedPlayer(unsigned int r,const string & fn,const string &ln,bool ht):
TableTennisplayer(fn,ln,ht)
{
rating = r;
}
其中 :Tablerennisplayer(fn,ln,ht)是成员初始化列表。它是可执行的代码,调用TableTennisPlayer构造函数。例如,假设程序包含如下声明:
RatedPlayer rplayer1(1140,"Mallory","Duck",true);
则 RealPlayer 构造函数将把实参“Mallory”、“Duck”和 true 赋给形参 f、In 和 ht,然后将这些参数作为实参传递给 TableTennisPlayer 构造函数,后者将创建一个嵌套TableTennisPlayer对象,并将数据“Mallory”、“Duck”和 true 存储在该对象中。然后,程序进入 RealPlayer 构造函数体,完成 RealPlayer 对象的创建,并将参数r的值(即1140)赋给rating成员(参见图13.2)。
如果省略成员初始化列表,情况将如何呢?
RatedPlayer::Ratedplayer(unsigned int r,const string & fn,const string &ln,bool ht)//what if no initializer list?
{
rating = r;
}
必须首先创建基类对象,如果不调用基类构造函数,程序将使用默认的基类构造函数,因此上述代码与下面等效:
Ratedplayer::Ratedplayer(unsigned int r,const string & fnconst string &ln,bool ht)//:TableTennisPlayer()
{
rating = r;
}
除非要使用默认构造函数,否则应显式调用正确的基类构造函数下面来看第二个构造函数的代码:
RatedPlayer::Ratedplayer(unsigned int r,const TableTennisPlayer & tp):TableTennisPlayer(tp)
{
rating = r;
}
这里也将 TableTennisPlayer 的信息传递给了 TableTennisPlayer 构造函数
TableTennisPlayer(tp)
由于tp的类型为 TableTennisPlayer&,因此将调用基类的复制构造函数。参见【0voice C++】基类没有定义复制构造函数,但第 12章介绍过,如果需要使用复制构造函数但又没有定义,编译器将自动生成一个。在这种情况下,执行成员复制的隐式复制构造函数是合适的,因为这个类没有使用动态内存分配(string成员确实使用了动态内存分配,但本书前面说过,成员复制将使用string类的复制构造函数来复制string 成员)。如果愿意,也可以对派生类成员使用成员初始化列表语法。在这种情况下,应在列表中使用成员名,而不是类名。所以,第二个构造函数可以按照下述方式编写:
//alternative version
Ratedplayer::Ratedplayer(unsigned int r,const TableTennisPlayer & tp):TableTennisPlayer(tp),rating(r)
{
}