面向对象程序设计的核心思想是数据抽象(封装)、继承、动态绑定(多态)。通过数据抽象,我们将类的接口(函数)与实现(数据成员)分离;使用继承,可以定义相似的类型并对相似关系建模;使用动态绑定,一定程度上忽略相似类型的区别,以同一的方式使用它们的对象。

派生类继承基类,基类定义所有类共有的成员,而每个派生类定义各自特有的成员。

1、基类和派生类

(1)基类

基类与一般类的定义相同:

class A{

  int a;

};

如果将某个类用作基类,则该类必须已经定义而非声明。在类名后添加final关键字可以防止继承。

(2)派生类

  派生类需要使用派生类列表,来指明继承自哪些基类,每个基类前面可以由访问说明符private、protected、public:

class B:public A{

  double b;

};

派生类继承基类的所有成员,但是对基类成员的访问权限与访问说明符有关。派生类可以添加新的成员。

2、虚函数

对于某些函数,派生类需要定义自己的函数与基类的版本做适当改变,此时基类可以将这些函数声明添加virtual关键字变成虚函数:

virtual int fun(int)const;

  • 任何构造函数之外的非静态函数都可以是虚函数,
  • 关键字virtual只能出现在类内部的声明语句中,而不能用于外部的函数定义。
  • 如果接类把一个函数声明成虚函数,该函数在派生类中也是虚函数。
  • 如果函数被声明成虚函数,则其解析过程发生在运行时,否则发生在编译时

派生类可以不改写基类的虚函数,直接继承;如果有需要覆盖,则必须要对重新定义的虚函数进行声明:

int fun(int)const override;;

具体做法是在形参列表后面、const成员函数的const关键字后面、引用成员函数的引用限定符后面添加一个关键字override。

(1)虚函数与默认实参

如果我们通过基类的引用或指针调用了虚函数,即使实际运行的是派生类的版本,我们也使用基类中定义的默认实参,此时传入派生类函数的是基类函数定义的默认实参。因此,如果虚函数使用了默认实参,基类和派生类中定义的默认实参最好一致。

(2)回避虚函数机制

如果我们希望代码执行某个版本的虚函数,使用作用域运算符实现这一目的:
p->A::fun();

该代码强行调用A的fun函数,而不管实际指向的对象类型是什么。通常当一个派生类的虚函数调用它覆盖的基类虚函数版本时,我们需要用到回避虚函数的默认机制。

(3)纯虚函数

纯虚函数是在虚函数的基础上发展而来,通过对继承的虚函数重新声明,通过在参数列表后面后面添加=0来声明一个纯虚函数

void fun()=0;//fun必须在其基类中是虚函数

  • =0只能出现在类内部的虚函数声明语句处
  • 纯虚函数可以只声明不定义。
  • 含有纯虚函数的类是抽象类,派生类对象如果没有覆盖抽象的基类,则其也是抽象类。
  • 我们不能创建一个抽象类的对象,可以定义其派生类的对象,前提是派生类覆盖了基类的纯虚函数。

3、动态绑定

(1)派生类到基类的类型转换

因为派生类对象中含有与其基类对应的组成部分,所以我们能把派生类对象当作基类来用:

A ItemA;

B itemB;

A *pa=&itemA;

pa=&itemB;//pa指向itemB的A类部分

A &ra=itemB;//ra绑定到itemB的A类部分

上述的转换称为派生类到基类的类型转换。

函数的运行版本根据实参的具体类型(指针或引用指向的是基类还是派生类)决定使用哪个虚函数,这种在运行时选择函数的版本被称为动态绑定(运行时绑定)动态绑定只有在我们通过指针或引用调用虚函数时才会发生。

(1)静态类型和动态类型

表达式的静态类型在编译时知道,它是变量声明是的类型或表达式生成的类型;动态类型是变量或表达式表示的内存中的对象的类型,动态类型在运行时才知。

如果表达式既不是引用也不是指针,则它的类型永远与静态类型一致。

之所以存在派生类向基类的类型转换时因为每个派生类对象都包含了基类的那部分,而基类的引用或指针可以绑定到该基类部分上。而不能将派生类的指针或引用指向基类,因为指针可能访问基类不存在的派生类成员。

基类指向派生类——可以

派生类指向基类——不行

3、派生类构造函数

尽管从语法上来说我们可以在派生类构造函数体内给它的公有或受保护的基类成员赋值,但最好不要这么做,要想与类的对象交互必须使用该类的接口,即使是派生类,在初始化对象的基类部分时也只能调用基类的构造函数来初始化那些从基类继承而来的成员。

每个类控制它自己的成员初始化过程。

派生类构造函数是通过构造函数初始化列表来将实参传递给基类构造函数的:

B( int va,double vb):A(va),b(vb){}

首先初始化基类部分,然后按照声明顺序初始化派生类的成员。

4、继承与静态成员

如果基类定义了一个静态成员,则在整个继承体系中只存在该成员的唯一定义,不论从基类继承了多少个派生类,对于每个静态成员来说只有一个

5、继承与访问说明符

访问说明符public、protected、private。

(1)基类中成员的访问说明符

public:谁都能访问。

private:只有自己类的成员函数或其友元能访问。

protected:自己类、友元、其派生类的成员、派生类的友元都能访问。但派生类的成员或派生类的友元只能访问派神类继承基类的那部分受保护成员,不能访问基类对象中的受保护成员。但是基类的友元可以访问基类对象中的所有成员。

总结就是:

  • 成员函数能访问自己类的所有成员,
  • 友元也能访问友元类的所有成员。
  • 派生类能和其友元能访问从基类继承来的的public和protected成员。
  • 派生类和其友元不能访问基类对象的protected和private成员。

(2)派生列表的访问说明符

派生列表的访问说明符的作用是将继承的基类中成员的访问说明符升级,限制派生类的对象(用户)对这些成员所能进行的操作;派生类的成员函数对基类所能进行的操作没有任何影响,有权限的还是有权限,无权限的还是没有权限。

public:成员的访问说明符没变,派生类用户可以访问基类中的public成员。

protected:public变成protected,派生类用户不能访问基类的所有成员。

private:所有成员变成private,派生类用户不能访问基类的所有成员。

(3)struct和class的区别

前面说过二者的区别是默认的访问说明符,一个是public一个是private

现在添加一个区别是默认的派生访问说明符,一个是public继承,一个是private继承。

转载于:https://www.cnblogs.com/StormWendy/p/8465693.html

c++面向对象的程序设计相关推荐

  1. 理解面向过程和面向对象的程序设计方法

    一.结构化程序设计 1,概念: 传统的结构化程序设计思想的核心是功能的分解.将问题分解为多个功能模块,根据模块功能来设计用于存储数据的数据结构,最后编写了过程(函数)对数据进行操作实现模块的功能.程序 ...

  2. 面向对象的程序设计——理解对象

    面向对象的程序设计 ECMA-262 把对象定义为:无须属性的集合,其属性可以包含基本值.对象或者函数. 理解对象 var person = new Object(); //创建对象 person.n ...

  3. javascript高级程序设计第3版——第6章 面向对象的程序设计

    第六章--面向对象的程序设计 这一章主要讲述了:面向对象的语言由于没有类/接口情况下工作的几种模式以及面向对象语言的继承: 模式:工厂模式,构造函数模式,原型模式 继承:原型式继承,寄生式继承,以及寄 ...

  4. 面向对象的程序设计在游戏开发中使用(一):类

    我并不是游戏开发的从业人员,甚至连软件开发都不是,但至少我是程序员. 我认为,一个[面向对象]的理念在学习过程中的重要性远大于对于代码本身含义的认识. 这一点可以在诸多书籍中得到论证,但很奇怪的一件事 ...

  5. JS面向对象的程序设计之继承-继承的实现-借用构造函数

    JS面向对象的程序设计之继承-继承的实现-借用构造函数 前言:最近在细读Javascript高级程序设计,对于我而言,中文版,书中很多地方翻译的差强人意,所以用自己所理解的,尝试解读下.如有纰漏或错误 ...

  6. [Python3]Python面向对象的程序设计

    [Python3]Python面向对象的程序设计 一.面向对象的程序设计的由来 1.第一阶段:面向机器,1940年以前 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行 ...

  7. python基础——面向对象的程序设计

    python基础--面向对象的程序设计 1 什么是面向对象的程序设计 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...

  8. Python之面向对象的程序设计

    Python之面向对象的程序设计 优点:解决了程序的扩展性,对某一个对象单独修改.会立刻反应到整个体系中,如对一个游戏中人物参数的特征和技能进行修改都很容易. 缺点:可控性差,无法向面向过程的程序设计 ...

  9. 面向对象的程序设计-电梯调度系统的设计、优化与测试

    面向对象的程序设计(2019)第二单元总结 I  对问题的初体验 在开始OO之旅前,对OO电梯早有耳闻.这一次终于轮到我自己实现OO电梯了.首先从顶层需求出发对电梯系统进行分析,对象包括电梯.任务和乘 ...

  10. Python学习之路9☞面向对象的程序设计

    Python学习之路9☞面向对象的程序设计 一 面向对象的程序设计的由来 见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.html 二 什 ...

最新文章

  1. 使用OpenCV实现车道线检测
  2. 双向链表的插入和删除算法描述
  3. VS2017常用、好用的快捷键
  4. 前端学习(3011):vue+element今日头条管理--关于编辑器代码段
  5. 回顾一下Unix哲学
  6. POJ 1459 Power Network
  7. JVM GC一篇通 - 基础与调优
  8. 无法向会话状态服务器发出回话状态请求
  9. 手机怎么解决同ip多账号_中海达RTK连接CORS账号后一直显示单点怎么解决?
  10. densenet代码解读
  11. linux 将ext2变成ext4文件系统
  12. 小程序项目:基于微信小程序的每日签到打卡——计算机毕业设计
  13. C# 阿里云视频点播
  14. 幼儿园计算机网络教室工作计划,2017年幼儿园教学工作计划范文
  15. 关于iOS 报Command failed with exit 128: git错误额解决方案
  16. 旧苹果电脑安装win10 双系统
  17. ASR_intern_summary
  18. 微信号名称乱码什么情况_微信号改成什么好?
  19. 双向广搜-HDU1401 Solitaire
  20. 问世到现在电子计算机的性能,一级计算机练习.doc

热门文章

  1. html前端 echarts图表使用详解
  2. OpenCV 开闭运算
  3. AutoCAD 2021简体中文版
  4. struts2获取服务器临时目录
  5. git 的右键快捷菜单恢复
  6. 2011考研英语词汇最佳记忆法 考量你的遗忘曲线
  7. (天国之扉文章抢救) 1/10/2003 总结?总结!
  8. Windows Messenger 5.1 [Download from Microsoft]
  9. MySQL 8.0 首个自适应参数横空出世
  10. 不再任人欺负!手游安全的进阶之路