C++中派生类和基类之间的特殊关系
派生类与基类之间有一些特殊关系。其中之一是派生类对象可以使用基类的方法,条件是方法不是私有的:
Ratedplayer rplayerl(1140,"Mallory","Duck",true);
rplayer1.Name(); //derived object uses base method
另外两个重要的关系是:基类指针可以在不进行显式类型转换的情况下指向派生类对象;基类引用可以在不进行显式类型转换的情况下引用派生类对象:
Ratedplayer rplayerl(1140,"Mallory","Duck",true);
TableTennisPlayer & rt = rplayer;
TableTennisPlayer * pt = &rplayer;
rt.Name(); //invoke Name() with reference
pt->Name(); //invoke Name() with pointer
然而,基类指针或引用只能用于调用基类方法,因此,不能使用“t或pt来调用派生类的 ResetRanking 方法。通常,C++要求引用和指针类型与赋给的类型匹配,但这一规则对继承来说是例外。然而,这种例外只是单向的,不可以将基类对象和地址赋给派生类引用和指针:
TableTennisPlayer player("Betsy","Bloop",true);
Ratedplayer & rr = player; // NOT ALLOWED
RatedPlayer * pr = player; // NOT ALLOWED
上述规则是有道理的。例如,如果允许基类引用隐式地引用派生类对象,则可以使用基类引用为派生类对象调用基类的方法。因为派生类继承了基类的方法,所以这样做不会出现问题。如果可以将基类对象赋给派生类引用,将发生什么情况呢?派生类引用能够为基对象调用派生类方法,这样做将出现问题。例如,将RatedPlayer:Rating()方法用于 TableTennisPlayer 对象是没有意义的,因为 TableTennisPlayer 对象没有 rating 成员。如果基类引用和指针可以指向派生类对象,将出现一些很有趣的结果。其中之一是基类引用定义的函数或指针参数可用于基类对象或派生类对象。参见【0voice C++】例如,在下面的函数中:
void Show(const TableTennisplayer & rt)
using std::cout;
cout << "Name:";
rt.Name();
cout << "\nTable:";
if(rt.HasTable())
cout <<"yes\n";
else
cout << "no\n";
形参 t是一个基类引用,它可以指向基类对象或派生类对象,所以可以在Show()中使用 TableTennis参数或 Ratedplayer 参数:
TableTennisPlayer player1("Tara","Boomdea",false);
Ratedplayer rplayer1(1140,"Mallory","Duck",true);
Show(player1); // works with TableTennisPlayer argument
Show(rplayerl); // works with RatedPlayer argument
对于形参为指向基类的指针的函数,也存在相似的关系。它可以使用基类对象的地址或派生类对象的地址作为实参:
void wohs(const TableTennisPlayer *pt);// function with pointer parameter
...
TableTennisPlayer playerl("Tara","Boomdea",false);
RatedPlayer rplayer1(1140,"Mallory","Duck",true);
Wohs(&player1); // works with TableTennisPlayer * argument
Wohs(&rplayer1); // works with RatedPlayer *arqument