码迷,mamicode.com
首页 > 编程语言 > 详细

c++入门之类继承初步

时间:2019-01-12 22:53:26      阅读:279      评论:0      收藏:0      [点我收藏+]

标签:包括   one   错误   类的构造函数   添加   连续   接口   ber   ini   

继承是面向对象的一种很重要的特性,先来复习基类的基本知识:

先上一段代码:

 1 # ifndef  TABLE00_H
 2 # define TABLE00_H
 3 # include "string";
 4 using std::string;
 5 class  Player
 6 {
 7 private:
 8     string first_name;
 9     string last_name;
10     bool SEAT;
11 public:  //注意,这里只是头文件,进行函数声明的地方
12     //Player(const string & fn = "none", const string & ln = "none", bool symbol = false);
13     Player(const string & fn , const string & ln , bool symbol);
14     //注意,在最开始设计类的时候,可能我们并没有注意到 要使用 &引用 和const,使用& 和const的契机是:
15       //1 使用& 是因为,初始化类型为 string类型或者c类型字符串,进行这种非基类数据类型复制的时候,都会耗费大量内存和时间,所以采用引用&
16       // 2 使用const 的契机: 因为这里采用了引用,这种做法是为了不改变被引用引用的对象。思考将引用符号去掉,是否还有加const的必要性?
17     void NameShow()const;
18     bool SeatVerify()const;
19     //思考:在函数名后面加const,是因为在写函数体之前就想好了函数的功能是否改变成员变量,如果函数的功能不改变成员变量,就添加const,
20     //说白了这是一种从顶层到底层的设计,我们明白了函数的功能不改变成员变量,所以为了防止写函数体的过程改变成员变量,我们加了一个const。
21     // 一般的 const加在谁的前面。就是用来修饰谁的,加在返回类型前面,就是修饰返回值,加在形参前面,即修饰形参,则加在函数名后面,是修饰函数体的,具体的也就是
22     //不改变类对象的成员值。即这种函数称之为常成员函数。
23     //思考:当函数代码比较短的时候,可否在头文件直接使用内联函数将函数体键入?
24     void SetSeat(bool);
25 
26 };
27 //以下为共有继承类声明部分
28 class RePlayer :public Player
29 {
30 private:
31     unsigned int ratio;
32 public:
33     RePlayer(unsigned int, const string & fn, const string & ln, bool symbol);
34     RePlayer(unsigned int, const Player & np);
35     int Ratio() const;
36     void InitialRatio(unsigned int);
37 };
38 
39 # endif

先复习基本知识:

    1  # ifndef TABLE00_H...# endif 表明:如果之前没有定义TABLE00_H段,则编译# ifndef TABLE00_H...# endif之间程序段,否则不编译,这 能够避免一个文件被多个重叠文件连续包含时报错,比如B头文件包含了A文件,C头文件包含了B文件和A文件,那么如果没加# ifndef TABLE00_H...# endif ,则会因为重复定义报错,因此在写头文件时,一律写上 # ifndef TABLE00_H...# endif可以避免程序的报错问题。

    2  对一个类而言,构造函数是十分重要的一个环节,构造函数存在的意义是:让私有成员变量被初始化,我们应当始终注意这一初衷,只有这样,我们才能设计正确的形参。

    3  我们应该注意引用&变量的使用契机,当传递的参数是复杂数据类型(比如类和c类型的字符串),由于巨大的内存开销和调度,采用引用的方式无疑是一种高效的方式

    4  上述代码段17,18,35行的函数成为:常成员函数,在此,先声明函数声明结尾const的作用,使得程序体不能改变私有成员变量的值(否则报错),比如成员显示函数,可以使用常成员函数

上述代码28-37行为继承类的生命,从这个声明我们可以得到这样一些基本信息与结论:

    1  继承类首先也是类,具有类的一般特性:包括私有成员、公有成员,以及构造函数。

    2  观察继承类的构造函数。发现其构造函数同样服从:让私有成员变量被初始化.但继承类继承了基类,因此也要对基类的成员进行初始化,说白了,要对所有的成员进行初始化。

易错:

    也许有人看了13,33,34行的代码,会发出这样的疑问:为何这里使用了引用变量却没有初始化,引用变量在定义变量时不是要进行初始化吗?

    回答我们在声明类,甚至在定义类的时候,本质工作是什么???本质工工作是:构造,构造一个数据类型,并不是在定义变量,只有我们在使用类(构造的数据类型)去定义对象的时候,我们才是真正的定义了一个变量,所以 定义类的过程,并不是定义变量的过程,所以并不必要对&进行初始化,说白了,此时的引用&只是一个空壳子,并不实际的分配内存,进行初始化这些功能。

进行了类声明之后,但成员函数还未得到定义,为此,给出类定义:

 

 1 # include "table00.h"
 2 # include "iostream"
 3 using std::string;
 4 using std::cout;
 5 using std::endl;
 6  /*class  Player  //如果在函数体文件再声明class Player则会出现重定义的情况!!!,所以采用这种做法是错误的。
 7 {
 8 private:
 9     string first_name;
10     string last_name;
11     bool SEAT;
12 public:
13     Player(const string & fn = "none", const string & ln = "none", bool symbol = false)
14     {
15         first_name = fn;
16         last_name = ln;
17         SEAT = symbol;
18     }
19     void  NameShow()const  //注意在函数体中,这个const也不能丢舎.
20     {
21         cout << first_name << "," << last_name << endl;
22     }
23     bool SeatVerify()const
24     {
25         return SEAT;
26     }
27     void SetSeat(bool change_seat)
28     {
29         SEAT = change_seat;
30     }
31 };*/
32 //验证上述写法和下述写法哪个更好。以及对于作用域有没有更好的表示方法。
33 //Player::Player(const string & fn = "none", const string & ln = "none", bool symbol = false)
34 Player::Player(const string & fn , const string & ln, bool symbol )
35 
36 {              
37     first_name = fn;
38     last_name = ln;
39     SEAT = symbol;
40 }
41 void Player:: NameShow()const  //注意在函数体中,这个const也不能丢舎.
42 {
43     cout << first_name << "," << last_name << endl;
44 }
45  bool Player:: SeatVerify()const
46 {
47     return SEAT;
48 }
49  void Player:: SetSeat(bool change_seat)
50 {
51     SEAT = change_seat;
52 }
53 //要认识到面向对象这个词的含义:函数的作用尽管也是为了完成一个功能,但更多的是完成对数据的操作,即我们更关注数据本身
54 // 成员函数的本质在于:服务于成员变量(通常情况是这样),所以在进行成员函数设计的时候,我们所关注的重点是:对成员变量进行何种操作,完成何种功能
55  //一定要注意主体对象是成员变量。
56 
57  RePlayer::RePlayer(unsigned int v, const string & fn, const string & ln, bool symbol) : Player(fn, ln, symbol)
58  {  
59      ratio = v;
60     // first_name = fn;    注意,如果我们试图直接访问基类私有变量,是有问题的
61     // last_name = ln;     但我们需要在调用继承类构造函数之前,调用基类构造函数。
62     // SEAT = symbol;
63  }
64    //这两条都是继承类构造函数,需要在调用之前调用基类构造函数,因此需要先初始化基类构造函数。
65  RePlayer::RePlayer(unsigned int v, const Player & np) : Player(np)
66  {                                              //需要注意的是:如果 前面定义 unsigned int v =0;则后面的np也要赋初值
67      //注意,这里的写法发生了重定义。
68      ratio = v;
69      // first_name = fn;    注意,如果我们试图直接访问基类私有变量,是有问题的
70      // last_name = ln;     但我们需要在调用继承类构造函数之前,调用基类构造函数。
71      // SEAT = symbol;
72  }
73  int RePlayer:: Ratio()const
74  {
75      return ratio;
76  }
77  
78  void RePlayer::InitialRatio(unsigned int initial)
79  {
80      ratio = initial;
81  }

 

关于成员函数(也被称为接口,其实很形象!!!)有以下内容需要说明:

    1  无论是基类的成员函数,还是继承类的成员函数,发现:成员函数都更侧重于:对成员变量(也称为实现,也很形象)进行了何种操作。虽然成员函数也描述了:完成了一个怎样的功能,但我们更侧重于:对成员变量完成了一种怎样的功能,也就是最终落脚点在于:成员变量发生了什么?因此,我们在写成员函数的时候,一定不能漫无目的,思考要完成一个什么功能但脱离了成员变量,一定要认识到我们的成员函数是紧紧的围绕成员变量展开的

    2 关注继承类的构造函数的实现:也就是上述,57和65行的代码。在初始化一个继承类成员(实际上包含了基类成员在内的所有成员)的时候,必然先初始化基类的成员变量,要调用继承类的构造函数,一定要首先调用其基类的构造函数,完成对基类成员变量先进行初始化。因此在进入继承类构造函数函数体之前,必然先要调用基类构造函数完成基类成员变量的初始化。

这也是为什么57行Player(fn, ln, symbol)与65行的 Player(np)会写在函数体{}的前面

    3  我们注意:60行和69行的代码,当我们试图去直接访问基类私有成员变量时,程序是禁止的,也就是说,我们只能通过基类的公有函数才能访问基类的私有成员。这一点保证了父类和子类的独立性关系。

 

   最终,我们给出函数的调用:

 

 1 # include "table00.h"
 2 # include "iostream"
 3 using namespace std;
 4 int main()
 5 {
 6     Player player1("jack", "cracy", true);
 7     player1.NameShow();
 8     Player player2(player1);
 9     player2.NameShow();
10     RePlayer player3(0, "robert", "lin", true);
11     player3.NameShow();
12     RePlayer player4(12,player2);
13     player4.NameShow();
14     system("pause");
15     return 0;
16 
17 }

 

从代码中,可以看到:继承类可以调用基类的公有函数。

 

c++入门之类继承初步

标签:包括   one   错误   类的构造函数   添加   连续   接口   ber   ini   

原文地址:https://www.cnblogs.com/shaonianpi/p/10261067.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!