C++继承一之公有继承

一般来说一个类可以继承于另外一个类,分别叫做派生类和基类,
派生类继承了基类的公有成员和保护成员以及实现,而私有成员只能通过
基类的公有方法进行访问
派生类应该包含如下信息:
1、继承类构造函数
2、需要额外增加的成员以及实现

我们引用C++ primer plus中的例子,当然这些例子我都是手动打过一遍的
<lastname<<", "<<firstname;="" }="" rateplayer::rateplayer(unsigned="" int="" r,const="" string="" &fn,const="" &ln,bool="" ht):tabletennisplayer(fn,ln,ht),rating(r){} <player3.rating();=""

点击(此处)折叠或打开

  1. #ifndef TABTEEN_H_
  2. #define TABTEEN_H_
  3. #include<iostream>
  4. using namespace std;
  5. class TableTennisPlayer
  6. {
  7.         private:
  8.                 string firstname;
  9.                 string lastname;
  10.                 bool hasTable;
  11.         public:
  12.                 TableTennisPlayer(const string &fn = "none",const string & ln ="none",bool ht=false);
  13.                 void Name() const;
  14.                 bool HasTable() const
  15.                 {return hasTable;};
  16.                 void ResetTable(bool v)
  17.                 {hasTable = v;};
  18. };
  19. class RatePlayer:public TableTennisPlayer
  20. {
  21.         private:
  22.                 unsigned int rating;
  23.         public:
  24.                 RatePlayer(unsigned int r=0,const string & fn="none",const string& ln="none",bool ht=false);
  25.                 RatePlayer(unsigned int r,const TableTennisPlayer& tp);
  26.                 unsigned int Rating() const
  27.                 {return rating;}
  28.                 void ResetRaing(unsigned int r)
  29.                 {rating = r;}
  30. };
  31. #endif
  32. TableTennisPlayer::TableTennisPlayer (const string& fn,const string &ln,bool ht):firstname(fn),lastname(ln),hasTable(ht){}
  33. void TableTennisPlayer::Name() const
  34. {
  35.         std::cout<<lastname<<", "<<firstname;
  36. }
  37. RatePlayer::RatePlayer(unsigned int r,const string &fn,const string &ln,bool ht):TableTennisPlayer(fn,ln,ht),rating(r){}
  38. //这里注意必须使用初始化列表的方式进行基类的初始化及TableTennisPlayer(fn,ln,ht)是必须的当然这里rating(r)不是必须的
  39. RatePlayer::RatePlayer(unsigned int r,const TableTennisPlayer& tp):TableTennisPlayer(tp),rating(r){}
  40.  //这里注意TableTennisPlayer(tp)调用了默认的复制构造函数,每个类都包含一个默认的复制构造函数
  41. 主函数
  42. #include<iostream>
  43. #include "tabtenn0.h"
  44. using namespace std;
  45. int main(void)
  46. {
  47.         TableTennisPlayer player1("Chuck","Blizzard",true);
  48.         TableTennisPlayer player2("Tara","Boomdea",true);
  49.         RatePlayer player3(1111,"gaopeng","Yjf",false);
  50.         player1.Name();
  51.         if(player1.HasTable())
  52.                 cout<<": has a table.\n";
  53.         else
  54.                 cout<<": hasn't a table.\n";
  55.         player2.Name();
  56.         if(player2.HasTable())
  57.                 cout<<": has a table\n";
  58.         else
  59.                 cout<<": hasn't a table.\n";
  60.         player3.Name();//TableTennisPlayer.Name()
  61.         cout<<" sorce: "<<player3.Rating();
  62.         if(player3.HasTable())
  63.                 cout<<": has a table\n";
  64.         else
  65.                 cout<<": hasn't a table.\n";
  66.         return 0;
  67. }

这里player3对象的类是RatePlayer基类是TableTennisPlayer,Name和HasTable方法都是TableTennisPlayer继承而来,
而Rating是在继承类RatePlayer中定义的

注意点:
1、RatedPlayer::RatedPlayer(unsigned int r,const string &fn,const string &ln,bool ht):TableTennisPlayer(fn,ln,ht),rating(r){}
这里注意必须使用初始化列表的方式进行基类的初始化及TableTennisPlayer(fn,ln,ht)是必须的当然这里rating(r)不是必须的 
   可以{rating = r;}声明   
下面的类型必须使用初始化列表的方式进行初始化
当使用如下方式的时候需要使用构造函数列表初始化成员
  1、const 成员
  2、引用&成员
  3、继承类的基类初始化
  4、本生就是类的成员
详细见
http://blog.itpub.net/7728585/viewspace-2122388/ 第8部分
2、RatePlayer(unsigned int r,const TableTennisPlayer& tp):TableTennisPlayer(tp),rating(r){} 
这里注意TableTennisPlayer(tp)调用了默认的复制构造函数,每个类都包含一个默认的复制构造函数,
在使用new等动态分配的时候显示定义深度复制构造函数是必须的,但是这里默认即可
详细见
http://blog.itpub.net/7728585/viewspace-2121213/ 第2部分深度复制
3、RatedPlayer::RatedPlayer(unsigned int r,const string &fn,const string &ln,bool ht):rating(r){}
注意这里没有调用构造函数,编译器将对基类使用默认的构造函数,也就是什么都不做,但是这样显然没有意义
在这里。
详细见
http://blog.itpub.net/7728585/viewspace-2120608/
下面是派生类构造函数相关要点
1、派生类构造函数需要调用基类构造函数初始化基类,并且在初始化列表中
2、派生类构造函数应该初始化新增的数据成员
3、派生类构造函数在初始化前就需要初始化基类,所以必须在初始化列表中
另外在析构函数中,程序会先调用派生类析构函数然后调用基类析构函数

其次,注意当基类的指针或者引用对象可以指向继承类的对象,因为继承类中一定包含了基类有的全部的信息,
但是反过来继承类的指针或者引用不你能指向基类的对象,因为基类并不包含继承类的全部信息,比如RatePlayer
中的rating在基类TableTennisPlayer中是不存在的,所以如下是成立的
同样我们知道默认的复制构造函数定义为
TableTennisPlayer(TableTennisPlayer& in)
但是由于TableTennisPlayer& 可以指向 RatePlayer&
所以TableTennisPlayer(RatePlayer& in)是成立的
也就是说
RatePlayer player3(1111,"gaopeng","Yjf",false);
TableTennisPlayer p3(player3);
成立
详细见
http://blog.itpub.net/7728585/viewspace-2121213/ 第2部分深度复制
同时
RatePlayer player3(1111,"gaopeng","Yjf",false);
TableTennisPlayer p4;
p4=player3;
也是成立的
调用默认的等值复制函数
原型
TableTennisPlayer& operator=(const TableTennisPlayer& st)
由于TableTennisPlayer&可以指向 RatePlayer&
所以TableTennisPlayer& operator=(const RatePlayer& st)
详细见:
http://blog.itpub.net/7728585/viewspace-2122388/ 第二部分
我们可以试一下,在原有的代码中加入: 
<endl;
<endl;

点击(此处)折叠或打开

  1. TableTennisPlayer p1(player3);
  2.      TableTennisPlayer p2;
  3.      p2=player3;
  4.      p1.Name();
  5.      cout<<endl;
  6.      p2.Name();
  7.     cout<<endl;
  8.    return 0;

</endl;
输出为:
Yjf, gaopeng
Yjf, gaopeng
没有问题
</endl;
</lastname<

时间: 2024-09-29 15:10:29

C++继承一之公有继承的相关文章

关于C++中公有继承、私有继承、保护继承的讨论

一.文章来由 简单明了的理由,老生常谈但是没真正解决的问题,想搞清楚这个问题. 二.冗长的定义 我们先来看看这些冗长的定义: 公有继承: 当类的继承方式为公有继承时,基类的公有成员和保护成员的访问属性在派生类中不变,而基类的私有成员不可直接访问.也就是说基类的公有成员和保护成员被继承到派生类中访问属性不变,仍作为派生类的公有成员和保护成员,派生类的其他成员可以直接访问它们.在类族之外只能通过派生类的对象访问从基类继承的公有成员. 私有继承: 当类的继承方式为私有继承时,基类中的公有成员和保护成员

c++-C++程序,公有继承之后成员的值变成了随机值,怎么回事儿

问题描述 C++程序,公有继承之后成员的值变成了随机值,怎么回事儿 #include #include using namespace std; const float Pi = 3.1415; class C { public: C(float r, float h) :Radius(r), high(h) {} protected: float Radius; float high; }; class Round :public C { public: void supArea(); voi

(一三八)多态公有继承

假如一个类继承另一个类,但有一个类方法,在不同类中,其行为是不同的. 换句话说,方法的行为,应取决于调用该方法的对象.这种较复杂的行为称为 多态--具有多种形态,即同一种方法的行为,随上下文而异.   有两种重要的机制可用于实现多态公有继承: ①在派生类中重新定义基类的方法: ②使用虚方法. 注:这两种机制共同使用       虚方法的关键字是:virtual 例如:virtual void show(); 虚方法的关键字,不在类外部使用,例如.cpp文件中的方法定义   虚方法的作用在于: 在

【C/C++学院】0822-类型转换函数与构造转换函数/类的继承/类的继承以及区别/继承静态成员与静态函数//继承实现代码重用/单继承QT案例/多继承简介以及实战/Gpu编程

类型转换函数与构造转换函数 #include<iostream> class fushu { public: explicit fushu(int num)//避免隐式转换,引发歧义 { x = num; y = num; } void print() { std::cout << x << "+" << y << "i" << std::endl; } operator int(); //不支

面向对象继承实例(a如何继承b问题)(自写)

经常会看到a如何继承b的问题:决定写一下,其实继承就是继承父级的属性和方法,感兴趣的朋友可以参考下哈,希望对大家有所帮助   复制代码 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>面向对象继承实例</title> <script type="text/javascript"> window.onl

对象-js中的方法继承和不使用继承添加方法的问题

问题描述 js中的方法继承和不使用继承添加方法的问题 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"&

浅谈JS继承_寄生式继承 &amp; 寄生组合式继承_javascript技巧

5.寄生式继承 与寄生构造函数和工厂模式类似,创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象. function createAnother(original){ var clone = Object.create(original); //通过调用函数创建一个新对象 clone.sayHi = function(){ //以某种方式来增强这个对象 alert("Hi"); }; return clone; //返回这个对象 } var person

js类式继承与原型式继承详解_javascript技巧

本文实例为大家分享了js类式继承与原型式继承相关代码,供大家参考,具体内容如下 1.js类式继承 /* -- 类式继承 -- */ //先声明一个超类 function Person(name) { this.name = name; } //给这个超类的原型对象上添加方法 getName Person.prototype.getName = function() { return this.name; } //实例化这个超 var a = new Person('Darren1') conso

浅析JS原型继承与类的继承_基础知识

我们先看JS类的继承 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JS类的继承</title> </head> <body> /* -- 类式继承 -- */ <script type="text/javascript"> //先声明一个超类 var Animal = function