1 对象的概念

面向对象(Object Oriented Analysis Design,OOAD)的思想把整个世界看成是由具有某种特征行为功能的基本单元——对象构成的。OOAD把一个对象的特征称为属性,把其行为称为一种方法。一个对象,可以接受外部信息,也可以向外部提供某种服务,我们可以将参数传递给对象,请求对象处理之后返回给我们,即提供了服务。

2 信息的隐藏与封装

C++与C基本的改变就是把函数和数据放进了结构之中,即C++类。为了达到隐藏的目的,C++提供了private、protected和public声明哪些东西能否以及如何被访问。 
虽然C++类很好用,当也不能一股脑儿都把不相干的数据和函数放到类中,要遵循最小化原则。

3 类的继承特性

什么是对象?对象就是类的一个实例(instance),如果把类比作房子的图纸,那么类就是建好的房子。 
什么是派生类和基类?派生类继承了基类的全部数据和函数,并具有自己私有的数据和函数,是“is a”的关系。比如人是一个基类,那么男人就是他的派生类,男人也是人。

4 动态特性

绝大部分情况下,程序的功能在编译之后固定下来了,我们称之为静态特性。相对的,如果是运行时才确定下来的,则称之为动态特性。 
动态特性主要包括:虚函数、抽象基类、动态绑定和多态(polymorphism)等等。

4.1 虚函数

有时候为了结构统一和管理方便,在基类定义一个接口函数,派生类分别继承并覆盖了这一接口函数。在运行时,动态的确定该用哪一个派生类的函数。这样的函数称为虚函数。一旦一个类里的某个函数被声明成了虚函数,那么其派生类的对应函数也会成为虚函数。 
为了提高程序的清晰性,最好在每个派生类显示的声明虚函数(加virtual关键字)。

4.2 抽象基类

如果将基类的虚函数声明为纯虚函数后该类就变成了抽象基类。方法是将虚函数“初始化”为0(在后边添加“=0”),这样告诉编译器:不要为该函数编址,阻止类的实例化。 
抽象基类的设计思想是“接口与实现分离”,因为抽象基类将数据和实现都隐藏在了实现类中,所以又被称为接口类。

4.3 动态绑定

理解动态绑定首先需要知道以下概念:

  • 绑定:将函数体和函数调用关联起来(一般通过函数指针)
  • 早绑定:在程序运行之前,即编译和链接是执行的绑定
  • 晚绑定:即动态绑定。在运行时,基于不同类型的对象,对函数调用不同的函数体是发生的绑定。

如果一个语言要实现动态绑定必须有某种机制去确定对象的具体类型,然后调用适当的成员函数。为了达到动态绑定的效果,派生类和基类中同名的函数必须要有相同的原型。

4.4 运行时多态

因为派生类和基类是“is a”的关系,所以一个派生类也可以当成一个基类来使用。因此这些派生类对象在面对同一个函数调用的时候会有不同的反应,这就是运行时的多态。 
C++实现运行时多态的方法有:

  • 经过隐式转换,令一个基类指针指向它的一个派生类对象
  • 通过这个指针调用基类的虚函数
  • 使用dynamic_cast<>和typeid运算符

综合使用C++的虚函数和多态,有如下突出的优点:

  • 只需要完成一次基类的调用,而不是完成每一个派生类的调用
  • 派生类的功能可以被基类指针引用,即向后兼容

4.5 多态数组

不要在数组中直接存放多态对象,换之以基类指针。 
- 通过基类指针删除一个优派生类对象组成的数组,结果将是未定义的!(内存空间问题) 
- 多态和指针算术运算不可混用,因此多态和数组不可混用

5 C++对象的内存模型

5.1 对象的内存映象

以两个简单的多态类为例

//基类A
class A{
public:
A(){...};
~A(){...};
virtual void func1() = ;
private:
int a;
static int b;
}; //派生类B
class B : public A{
public:
B(){...};
~B(){...};
virtual void func1(){...};
void func2(){...};
private:
int c;
static int d;
};

一个基本的对象模型有如下几个规则:

  • 非静态数据成员被放在每一个对象体内,为对象所专有
  • 静态数据成员放在程序的静态存储区内被该类所有对象共享,因此只存在一份
  • 静态或非静态成员函数放在程序的代码段内被该类所有对象共享,因此也只存在一份
  • 类类嵌套定义的各种类型(如typedef、class、struct、union、enum等)和放在类外面的定义除了作用域不同外没有本质的区别

构成对象本身的只有数据,任何成员函数都不属于任何一个对象。非静态成员函数与对象的关系就是绑定,绑定的中介是this指针。

  • 派生类继承基类的非静态成员
  • 每一个多态类都创建一个虚函数指针数组(vtable),该类所以虚函数(继承的或新增的)的地址都保存在这张表里
  • 多态类的每一个对象都有一个类型为指向函数指针的指针——vptr,它总是指向所属类的vtable
  • 如果基类已经插入了vptr,则派生类将继承和重用vptr
  • 如果派生类从多个多态基类继承,则派生类将在每个继承分支上继承多个vptr,生成对应的多个vtable数组
  • vptr在派生类对象中的相对位置不会因为继承层次的增加而改变
  • 为了支持RTTI,为每一个多态类创建一个type_info对象,并将其地址保存在vtable中的固定位置(一般在首部)

派生类B的对象模型如下图所示:

C++面向对象的设计思想——小结的更多相关文章

  1. 面向对象设计思想和MVC设计模式

    虽然之前学习Java时有接触过面向对象的设计思想,但因当时Java没学好.所以导致这两天讲php的面向对象设计时,感到没有头绪,这也反应了我练习少和逻辑能力的不足.而MVC设计思想 面向对象就是要将系 ...

  2. linux设备驱动的分层设计思想--input子系统及RTC

    转自:linux设备驱动的分层设计思想 宋宝华 http://blog.csdn.net/21cnbao/article/details/5615493 1.1 设备驱动核心层和例化 在面向对象的程序 ...

  3. python 面向对象设计思想发展史

    这篇主要说的是程序设计思想发展历史,分为概述和详细发展历史 一,概述 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的 指令和数 据.简单来 ...

  4. 面向对象的编程思想和Java中类的概念与设计

    面向对象的编程思想学习,面向对象内容的三条主线;1.java类及类的对象2.面向对象的三大特征3.其他关键字学习内容:3.1面向对象与面向过程面向对象与面向过程在应用上的区别 Java中类的概念与设计 ...

  5. 使用Unity3D的设计思想实现一个简单的C#赛车游戏场景

    最近看了看一个C#游戏开发的公开课,在该公开课中使用面向对象思想与Unity3D游戏开发思想结合的方式,对一个简单的赛车游戏场景进行了实现.原本在C#中很方便地就可以完成的一个小场景,使用Unity3 ...

  6. javascript继承机制的设计思想(ryf)

    我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...

  7. Volley设计思想和流程分析

    本文是对Volley思路的整体整理,并不是Volley教程,建议有Volley使用经验,但是对Volley整体不是很清楚的同学阅读. 我认为,弄清整体的流程很重要,以避免一叶障目不见泰山的囧境,而对于 ...

  8. javascript 继承机制设计思想

    作者: 阮一峰 原文链接:http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_java ...

  9. 转:Javascript继承机制的设计思想

    我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...

随机推荐

  1. TCP连接的建立以及利用tcpdump分析连接建立的过程(转)

    原文地址:http://www.cnblogs.com/coser/archive/2010/12/05/1968812.html 一.实验目的 实验1_1: 使用Freebsd/Linux操作系统下 ...

  2. 在wamp中直接进入项目

    这个问题困扰了我很久, 暂时我解决了一半. 进入localhost的页面如图一: 可以看到 我有两个projects,但是点击后会直接转跳到这样的页面 例如点击phyfitness_proj,如图二所 ...

  3. Bind for 0.0.0.0:80 failed: port is already allocated.解决方案

    一句话总结就是容器占用的port还没有完全释放 查看进程,发现相关的容器并没有在运行,而 docker-proxy 却依然绑定着端口: $ docker ps 检查docker镜像 $ ps -aux ...

  4. 常用HTML小部件

  5. HDU 5307 He is Flying (生成函数+FFT)

    题目传送门 题目大意:给你一个长度为$n$的自然数序列$a$,定义一段区间的权值为这一段区间里所有数的和,分别输出权值为$[0,\sum a_{i}]$的区间的长度之和 想到了生成函数的话,这道题并不 ...

  6. NOIP2018提高组省一冲奖班模测训练(五)

    NOIP2018提高组省一冲奖班模测训练(五) http://www.51nod.com/Contest/ContestDescription.html#!#contestId=79 今天有点浪…… ...

  7. java的值传递与引用传递

    一. 经常搞不清楚,当一个对象做为参数传入到方法中时,为啥有时候值能被改变,有时候又不会改变,以下说明原因: 1.当传入的参数,在方法中能被改变的为 引用传递 2.当传入的参数,在方法中没被改变的为 ...

  8. JavaScript 事件对内存和性能的影响

    程序代码: <%-- Created by IntelliJ IDEA. User: 乔克叔叔 Date: 2017/12/26 Time: 16:45 To change this templ ...

  9. soapui测试接口使用步骤

    1.新建项目 2. 定义接口 url输入接口 3.新建测试集 选择项目,右键 4.在测试集下新建测试用例 5.在测试步骤中导入要测试的请求 6.run

  10. 浙大PAT考试1013~1016(最伤的一次。。)

    我能说我1016WA了几天都不得最后还是拿别人代码交的么. .. 真心找不到那个神数据.. . 自己把整个程序的流程都画出来了.细致推敲是木有问题的啊... 题目地址:点击打开链接 先从1013開始介 ...