类继承小总结

  • 类继承的功能:
    1,在已有类的基础上添加功能。
    2, 可以给类增加数据。eg:对于一个表示人的类,可以派生一个类,添加人是否可以飞行这个数据成员(bool canfly;)
    3,可以修改类方法的行为。
  • 成员初始化语法:
    对于以下的类,可以有两种定义构造函数的方法:

     1 class TableTennisPlayer
     2  {
     3      private:
     4          string firstname;
     5          string lastname;
     6          bool hasTable;
     7      public:
     8          TableTennisPlayer(const string & fn = "none",
     9                  const string & ln = "none", bool ht = false);
    10          ....
    11  }

    第一种,在函数体内初始化成员

    1 TableTennisPlayer::TableTennisPlayer(const string & fn,
    2          const string & ln, bool ht)
    3  {
    4      firstname = fn;
    5      lastname = ln;
    6      hasTable = ht;
    7  }

    第二种,使用成员初始化列表语法

    1  TableTennisPlayer::TableTennisPlayer(const string & fn,
    2          const string & ln, bool ht) : firstname(fn),
    3          lastname(ln), hasTable(ht)  {  }

    第一种方法首先为firstname调用string的默认构造函数,在调用string的复制运算符将firstname设置为fn。但是,初始化列表语法(第二种方法)会直接使用string的复制构造函数将firstname初始化为fn。很明显,初始化列表语法步骤少性能好,而且更简洁。

  • 那么派生类和基类的关系如何?这里就公有派生谈一下。
    1,派生类对象存储了基类的数据成员(派生类继承了基类的实现)(并不是所有派生类都回继承基类的实现)
    2,派生类对象可以使用基类的方法(派生类继承了基类的接口)
    使用公有派生,基类的公有成员将成为派生类的公有成员,基类的私有部分也成为派生类的一部分,但只能通过基类的公有和保护方法访问。
  • 需要在继承特征中添加什么呢?
    1,派生类需要自己的构造函数。
    2,派生类可以根据需要添加额外的数据成员和成员函数。
  • 构造函数:访问权限的考虑
    派生类不能直接访问基类的私有成员,而必须通过基类方法进行访问。也就是说,要想访问修改基类的私有成员,必须要通过派生类的对象调用方法。现在假设,我们要通过派生类的构造函数初始化基类的私有数据成员和派生类数据成员。有点像这样:(假设RatedPlayer是TableTennisPlayer的派生类)
    1 RatedPlayer::RatedPlayer(const string & fn, const string & ln,
    2          bool ht, unsigned int ra)
    3  {
    4      firstname = fn;
    5      lastname = ln;
    6      hasTable = ht;
    7      rating = ra;
    8  }

    问题是,这么做是不行的。因为派生类的构造函数没有访问修改基类的权限。这个时候,前面说的成语初始化列表语法就派上用场了!下面直接看正确用法

    1 RatedPlayer::RatedPlayer(const string & fn, const string & ln,
    2          bool ht, unsigned int ra) : TableTennisPlayer(fn, ln, ht)
    3  {
    4      rating = ra;
    5  }

    创建派生类对象时,程序首先创建基类对象!从概念来说,这意味着基类对象应该在程序进入派生类构造函数之前就被创建。在这儿,初始化成员列表语法就是使基类对象被优先创建!!!
    总结来讲,派生类构造函数的要点如下:
    1,首先创建基类对象。
    2,派生类构造函数应该通过成员初始化列表语法将基类信息传递给基类构造函数,从而优先创建基类对象。
    3,派生类构造函数应初始化派生类新增的数据成员。

  • 再说成员初始化列表语法:
    出虚基类外,类只能将值传递会相邻的基类,但后者可以用相同的机制将信息传递给相邻的基类,以此类推。这就像接力棒比赛,将棒比喻为信息就行。
  • 派生类和基类之间的特殊关系:
    1,派生类对象可以直接使用基类的方法,前提是方法不是私有的。若是私有的,可以通过间接使用,即将基类的私有方法镶嵌再派生类的方法中。
    2,基类的引用(指针)可以在不进行显式类型转换的情况下,指向派生类对象。(这一点十分重要,乃派生之精华)
    对于第二点:c++要求引用(指针)类型与赋给的类型匹配,但这对继承来说,是个例外,要注意的是:派生类的引用(指针)不可指向基类,即不可逆。
    当一个函数(方法)的形参的类型是基类引用,那么可以将派生类的对象或者基类的对象作为实参。(理解这句话,十分重要!!)
时间: 2024-10-19 05:03:47

类继承小总结的相关文章

关于Swift类继承的一点小问题

别人已经写过很多关于Swift类继承的文章,这里我只是为了补充一点菜鸟教程继承上没有明面说明的东西,菜鸟教程关于类继承的网站:http://www.runoob.com/swift/swift-inheritance.html 关于这个问题,另一篇博客也写了这个: http://blog.csdn.net/binglan520/article/details/52662815 父类里面所有的属性 在定义时可以不给出初始值,在init函数里面赋予值就行了,而子类的属性 在定义时必须给出初始值,不然

模板类继承模板类

今天写的代码提交到OJ上就出现这样的错误,但是vs并不会出错. '_elem' was not declared in this scope 原因在于模板类继承模板类,子类看不见父类的成员. 但是VC++做了一些小拓展,可以不适用this->就调用父类成员. gcc在扫描到模板类时就要求确定每一个成员在哪里声明的,VC++在类实例化之后再检测,就不会有这个问题. 可以使用以下方式解决: 方法1: 使用this template<typename T> class A { protecte

C++父子类继承时的隐藏、覆盖、重载

存在父子类继承关系时,若有同名成员函数同时存在,会发生隐藏.覆盖和重载这几种情况.对于初学者也比较容易混淆,为此,我整理了一下我的个人看法,仅供参考.希望对大家理解有帮助,也欢迎指正. 1.父子类继承关系: 子类复制父类全部成员 首先,理解父子类的继承关系是怎样发生的.在此基础上就很容易理解它们之间的关系和区别. 每一个类有它自己的成员变量和成员函数,是一个独立的空间整体.当子类继承父类时,会将父类的全部成员全部复制一份,作为子类的成员,但是,同时也会标记这些成员是从父类中继承的,与子类本身的成

C++——类继承以及类初始化顺序

对于类以及类继承, 几个主要的问题:1) 继承方式: public/protected/private继承. 这是c++搞的, 实际上继承方式是一种允许子类控制的思想. 子类通过public继承, 可以把基类真实还原, 而private继承则完全把基类屏蔽掉. 这种屏蔽是相对于对象层而言的, 就是说子类的对象完全看不到基类的方法, 如果继承方式是private的话, 即使方法在基类中为public的方法. 但继承方式并不影响垂直方向的访问特性, 那就是子类的函数对基类的成员访问是不受继承方式的影

C++类继承中内存的布局

1 前言       了解你所使用的编程语言究竟是如何实现的,对于C++程序员可能特别有意义.首先,它可以去除我们对于所使用语言的神秘感,使我们不至于对于编译器干的活感到完全不可思议:尤其重要的是,它使我们在Debug和使用语言高级特性的时候,有更多的把握.当需要提高代码效率的时候,这些知识也能够很好地帮助我们. 本文着重回答这样一些问题: 1* 类如何布局? 2* 成员变量如何访问? 3* 成员函数如何访问? 4* 所谓的"调整块"(adjuster thunk)是怎么回事? 5*

scala学习手记13 - 类继承

在scala里,类继承有两点限制: 重写方法需要使用override关键字: 只有主构造函数才能往父类构造函数中传参数. 在java1.5中引入了override注解,但不强制使用.不过在scala中要想重写方法必须使用override关键字.如果确实重写了父类的方法又不使用override关键字的话,则会在编译时报错,提示没有使用override修饰符. scala的副构造函数必须调用主构造函数或是另一个副构造函数.只有在主构造函数中才能向父类的构造函数中传递数据.可以看出来主构造函数如同父类

sizeof 和类继承 虚继承 求类大小

代码: #include <iostream> using namespace std; /* class a{ float k; // 4字节 virtual void foo(){} //有一个4字节的指针指向自己的虚函数表 }; class b : virtual public a{ virtual void f(){} }; 有这样的一个指针vptr_b_a,这个指针叫虚类指针,也是四个字节:还要包括类a的字节数,所以类b的字节数就求出来了. 运行结果: 8 16 */ /* clas

JS中“类”继承和原型继承

类继承: 先用函数构造器创建了一个“类”Student,然后在Student原型上定义了一个方法sayHello,然后创建了一个"类“PrimaryStudent,用apply()初始化PrimaryStudent. 然后让PrimaryStudent的原型等于Student创建的对象,并把PrimaryStudent原型上的构造器指向当前”类“,即PrimaryStudent,注意红色加粗部分. 1 function Student(name){ 2 this.name = name; 3 }

javascript伪类继承修订版

原先文章中提到的伪类继承,超类的构造函数会被执行两次,所以效率上会有点问题,看了高级程序之后,发现原来还可以改进,只需要用一个函数来实现继承即可. function inherit(subClass, superClass) { function F() {} //创建临时构造函数 F.prototype = superClass.prototype //将超类的原型作为临时构造函数的原型 var prototype = new F() //实例化临时函数,到这里其实是把superClass复制