面向对象编程的主要目的之一是:提供可重用的代码。尤其是项目很庞大的时候,重用测试过的代码比重新编码代码要好得多。

C++提供了更高层次的重用性。其中之一就是继承这个概念。

一些厂商提供了类库。类库由类声明和实现构成。类库通常是由源代码组成的,这意味着可以对其进行修改,以满足需求。但是也可以用类继承的方式,来扩展和修改类。这比修改代码的方法更好。正如继承一笔财产要比自己白手起家更容易。

继承的基本实现非常简单,但是要对继承进行管理,使之在所有情况下都能正常使用,则需要做一些调整。所以继承有简单的一面,也有复杂的一面。

一个简单的类开始

从一个类派生出另一个类时,原始类称为基类,继承类称为派生类。

基类的私有部分将称为派生类的一部分,但只能通过基类的公有和保护方法访问。

基类的公有成员将称为派生类的公有成员。

派生类对象存储了基类的数据成员(派生类继承了基类的实现);

派生类对象可以使用基类的方法(派生类继承了基类的接口);

派生类需要添加自己的构造函数;

派生类可以根据自身需要添加额外的数据成员和成员函数;

构造函数:访问权限的考虑

派生类不能访问基类的私有成员,而必须通过基类方法进行访问。

因此派生类构造函数必须使用基类构造函数;

创建派生类对象时,程序首先创建基类对象。从概念上讲,这意味着基类对象应当在程序进入派生类构造函数之前被创建。->C++使用成员初始化列表来完成这种工作。

RatedPlayer::RatedPlayer(unsigned int r, const string & fn, const string & ln, bool ht):TableTennisPlayer(fn,ln,ht)

{

rating = r;

}

如果省略了基类构造函数的话:

RatedPlayer::RatedPlayer(unsigned int r, const string & fn, const string & ln, bool ht)

{

rating = r;

}

首先还是创建基类对象,如果不调用基类构造函数,程序将使用默认的基类构造函数

因此上述代码与下面等效:

RatedPlayer::RatedPlayer(unsigned int r, const string & fn, const string & ln, bool ht):TableTennisPlayer()

{

rating = r;

}

除非要使用默认构造函数,否则应该显式调用正确的基类构造函数。

还有一种构造函数代码:

RatedPlayer::RatedPlayer(unsigned int r, const TableTennisPlayer & tp):TableTennisPlayer(tp)

{

rating = r;

}

这里也是将TableTennisPlayer的信息传递给了TableTennisPlayer构造函数。

这种方式将调用基类的复制构造函数,如果基类没有定义复制构造函数,但又要使用它,则编译器将自动生成一个。

甚至还可以对派生类成员使用成员初始化列表语法:

RatedPlayer::RatedPlayer(unsigned int r, const TableTennisPlayer & tp):TableTennisPlayer(tp),rating(r)

{

}

派生类构造函数的要点总结:

首先创建基类对象;

派生类构造函数应通过成员初始化列表(TableTennisPlayer(tp))将基类信息传递给基类构造函数;

派生类构造函数应初始化派生类新增的数据成员(rating = r)。

如果没有提供显示构造函数,将使用隐式构造函数。

理解派生类对象创建过程的对象创建顺序:先创建基类对象,在创建派生类对象;

释放对象的顺序创建对象的顺序相反:首先执行派生类的析构函数,然后自动调用基类的析构函数。

成员初始化列表:(TableTennisPlayer(tp))

派生类构造函数可以使用初始化器列表机制将值传递给基类构造函数。

derived :: derived(type1 x, type2 y) : base(x,y)

{

...

}

Derived是派生类,base是基类。X和Y是基类构造函数使用的变量。

如果派生类构造函数接收到参数10和12,这种机制将把10和12传递给定义为接受这些类型的参数的基类构造函数。类只能将值传递回相邻的基类。虚基类除外,虚基类可以使用相同的机制将信息传递给相邻的基类,以此类推。如果没有在成员初始化列表中提供基类构造函数,程序将使用默认的积累构造函数。成员初始化列表只能用于构造函数。

使用派生类

使用派生类,程序必须要能够访问基类声明。可以把两个类的声明放在同一个头文件中,也可以放在不同的头文件中。

派生类和基类之间的特殊关系

派生类可以使用基类的方法,条件是方法不是私有的。

基类指针可以再不进行显式类型转换的情况下指向派生类对象。

基类引用可以再不进行显式类型转换的情况下引用派生类对象。

但是基类指针和引用只能调用基类的方法。

C++中要求引用和指针类型与赋予的类型匹配,但这一规则对继承来说是例外。这例外是单向的,也就是说不能将基类对象和地址赋给派生类引用和指针。

但是这种关系是单向的,不能将基类对象和地址赋给派生类引用和指针。

这样要求是有道理的:如果允许基类引用隐式地调用派生类方法,则可以使用基类引用为派生类对象调用基类的方法。因为派生类继承了基类的方法,所以这样做不会有问题。

如果可以将基类对象赋给派生类引用,将发生什么情况?派生类引用能够为基类对象调用派生类方法,这是没有意义的。例如TableTennisPlayer没有rating成员。

基类引用和指针可以指向派生类对象,将出现一些很有意思的现象:

 

C++_类继承1-从一个简单的类开始的更多相关文章

  1. 类的编写模板之简单Java类

    简单Java类是初学java时的一个重要的类模型,一般由属性和getter.setter方法组成,该类不涉及复杂的逻辑运算,仅仅是作为数据的储存,同时该类一般都有明确的实物类型.如:定义一个雇员的类, ...

  2. .Net Core 3.0后台使用httpclient请求网络网页和图片_使用Core3.0做一个简单的代理服务器

    目标:使用.net core最新的3.0版本,借助httpclient和本机的host域名代理,实现网络请求转发和内容获取,最终显示到目标客户端! 背景:本人在core领域是个新手,对core的使用不 ...

  3. Python——一个简单的类的创建和应用

    1.创建类,设置属性和给属性设定默认值,设置方法并访问类的属性: 2.利用类创建多个实例,以及调用类的方法的两种办法: 3.设置更新属性的函数,并更新实例的属性. class dog(object): ...

  4. Lua程序设计(三)面向对象实现一个简单的类

    1.Lua面向对象实现步骤 ①创建一个全局表(称之为元表) ②设置这个元表的__index值(值通常为元表自己,这样就能通过__index查找到对应的属性和方法)__index 赋值其实是一个func ...

  5. 【数据结构与算法】Java制作一个简单数组类

    bobo老师的玩转算法系列–玩转数据结构 简单记录 文章目录 不要小瞧数组 - 制作一个数组类 1 .使用Java中的数组 数组基础 简单使用 2.二次封装属于我们自己的数组 数组基础 制作属于我们自 ...

  6. C++类和对象的一个简单的实例

    题目:找出一个整形数组中的元素的最大值 下面,我们用类和对象的方法来做. #include<iostream> using namespace std; class Array_max{ ...

  7. c++类的基本形式(一个简单类的简单sample,命名空间)

    有人把类说成是占用固定大小内存块的别名,其定义时不占用空间 #include<iostream> #include<string> using namespace std; c ...

  8. c++有关构造函数、析构函数和类的组合的一个简单例子

    来源链接 实验四(下) 代码 #include <iostream> using namespace std; enum CPU_Rank {P1 = 1, P2, P3, P4, P5, ...

  9. 如何在C#中使用sqlite,一个简单的类

    </pre><pre name="code" class="csharp"> using System.Collections.Gene ...

随机推荐

  1. 【CF#338D】GCD Table

    [题目描述] 有一张N,M<=10^12的表格,i行j列的元素是gcd(i,j) 读入一个长度不超过10^4,元素不超过10^12的序列a[1..k],问是否在某一行中出现过 [题解] 要保证g ...

  2. linux 下搭建LAMP

    http://www.mizuiren.com/414.html 写的非常好

  3. 生成ico格式图标

    ico格式可参考如下链接: http://msdn.microsoft.com/en-us/library/ms997538.aspx http://en.wikipedia.org/wiki/ICO ...

  4. 在ubuntu12.04上安装6款顶级漂亮的BURG主题

    BURG 基本上是一个基于GRUB的Linux引导装载程序.BURG格有一个高度可配置的菜单系统,可选择文本和图形模式.简而言之,BURG可广泛定制,有良好免费的BURG主题.选择自己最喜欢的,下面我 ...

  5. 解决在Python中使用Win32api报错的问题,No module named win32api

    一.系统环境 操作系统: Win7 64位 Python:3.7.0 二.在使用import win32api时,报错:No module named win32api 网上查到有下面解决办法: 方法 ...

  6. Linux编译提速

    一.简介 项目越来越大,重新编译整个项目是一件很费时的事,总结可以帮助提速方法,如下: 1)tmpfs: 解决IO瓶颈,充分利用本机内存资源 2)make -j: 充分利用本机计算资源 3)distc ...

  7. python文件复制移动shutil模块

    shutil.copyfile( src, dst) 从源src复制到dst中去.当然前提是目标地址是具备可写权限.抛出的异常信息为IOException. 如果当前的dst已存在的话就会被覆盖掉 s ...

  8. 3.python 发送邮件之smtplib模块

    SMTP(Simple Mail Transfer Protocol)是简单邮件传输协议,它是一组用于由源地址到目的地址的邮件传输规则. python中对SMTP进行了简单的封装,可以发送纯文本邮件, ...

  9. Ref 和out

    out 关键字会导致参数通过引用来传递.这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化.若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字.例如 ...

  10. JS Img对象获取图片高度宽度(兼容Chrome)

    一般获取图片高度宽度的写法: var img = new Image();img.src = imgsrc;var imgWH = CalcImgTiple(img.width, img.height ...