C++ 程序设计 读后感

这本书应该算这边,已经是读的第三遍了,一直用本子做笔记,突然举得我应该把笔记心的写在博客上,便于自己的翻阅和记忆;真的是每一遍都有不同的收获,前两遍在阅读的时候,我真的还不太懂什么是C++,什么是继承、组合、virtual函数、类,但我读这边时,也就是这几天,突然举得自己有很大的提高,希望这是我开发生涯的一个好的开始,自己一定要再接再厉,不断地修炼自己;

第12章 多态和虚函数

在同一个类中是不能定义两个名字相同、参数个数和类型都相同的函数,否则就是“重复定义”。但是在类的继承层次结构中,在不同的层次中可以出现名字相同、参数个数和类型相同而功能不同的函数。这是合法的,因为不在同一个类中。编译系统按照同名覆盖的原则决定调用的对象。

虚函数的作用,是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。

virtual viod display();

当把基类的某个成员函数声明为虚函数后,允许在其派生类中对该函数重新定义,赋予它新的功能,并且可以通过指向基类的指针指向同一类族中的不同类的对象,从而调用其中的同名函数。由虚函数实现动态多态性就是:同一类族中不同类的对象,对同一函数调用作出不同的相应。

虚函数的使用方法是:

(1)在基类用virtual声明成员函数为虚函数。这样可以在派生类中重新定义此函数,为它赋予新的功能,并能方便地调用。

在类外定义虚函数时,不必再加virtual.

(2)在派生类中重新第一次函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体。

C++规定,当一个成员函数被声明为虚函数后,其派生类中同名函数都自动成为虚函数。因此在派生类重新声明该虚函数时,可以加virtual,也可以不加,但习惯上一般在每一层声明该函数时都加vitrual,是程序更加清晰。

如果在派生类中没有对基类的虚函数重新定义,则派生类简单地继承其直接基类的虚函数。

(3)定义一个指向基类对象的指针变量,并使他指向同一类族中的莫以对象。

(4)通过该指针变量调用此虚函数,此时调用的就是指针变量指向的对象的同名函数。

函数重载处理的是同一个层次上的同名函数问题,而虚函数处理的是不同派生层次上的同名函数问题,前者是横向重载,后者可以理解为纵向重载。但与重载不同的是:同一类组的虚函数的首部是相同的,而函数重载时函数的首部是不同的(参数个数和类型不同)。

静态关联与动态关联

确定调用具体对象的过程成为关联。

函数重载和通过对象名调用的虚函数,在编译实际可确定其调用的虚函数属于那一个类,其过程称为静态关联,由于是在运行前进行关联的,故称为早期关联。函数重载属静态关联。

在运行阶段把虚函数和类对象“绑定”在一起,一次,此过程称为动态关联。这种多态性是动态多态性,既运行阶段的多态性。(也称为滞后关联);

在什么情况下应当声明虚函数:

(1)类的继承层次结构中,对基类的虚函数重新定义;

(2)一个成员函数被声明为虚函数后,在同一个类族中的类就不能在定义一个非virtual 的当该虚函数具有相同的参数(包括个数和类型)和函数返回值类型的同名函数。

当带有虚函数时,编译系统会为该类构造一个虚函数表(vtable),它是一个指针数组,存放每个虚函数的入口地址。

虚析构函数:

将基类的析构函数声明为虚函数,这将是所有的派生类的析构函数自动成为虚函数。这样,如果程序中用delete运算符准备删除一个对象,而delete运算符的操作对象是指向派生类对象的基类指针,则系统会调用相应类的析构函数。

构造函数不能声明为虚函数。这是因为在执行构造函数时类对象还未完成建立过程,当然谈不上函数和类对象的关联。

纯虚函数与抽象类

一、纯虚函数:

vittual flot area() const =0; //存续函数

这就将area声明为一个纯虚函数。纯虚函数是在声明虚函数是被“初始化”为0的函数。声明纯虚函数的一般形式是

virtual 函数类型 函数名 (参数表类)=0;

注意

1 纯虚函数没有函数体;

2 最后面的“=0”并不表示函数返回值为0 ,它只起形式上的作用,告诉编译系统“这是存续函数”;

3 这是一个声明语句,最后应该有分号;

纯虚函数只是函数 的名字而不具备函数的功能,不能被调用;可以说他是“徒有其名,而无其实”。他只是通知编译系统“在这里声明一个虚函数,留待派生类中定义”。

在派生类中对此函数提供定义后,它才能具备函数的功能,可以被调用;

纯虚函数的作用是在基类中为其派生类保留一个函数名字,以便派生类根据需要对他进行定义。如果基类中没有保留函数名字,则无法实现多态性。

二 抽象类

定义这些类的唯一目的使用它作为基类去建立派生类;

不用来定义对象而只作为一种基本类型用作继承的类,称为抽象类,由于它常用作基类,通常称为抽象基类。

凡是含有纯虚函数的类都是抽象类。因为纯虚函数是不能被调用的,包含纯虚函数的类是无法建立对象的。抽象类的作用是作为一个类族的共同基类,或者为一个类族提供一个公共接口。

在抽象类里定义的虚函数后纯虚函数,在派生类中,如果用到,就重新定义;

(1)静态关联 :

先定义类对象,然后通过类对象调用类里的函数,这属于静态关联,在编译阶段就能确定调用哪个类的函数。同时用重载运算符“<<”来输出个对象的信息,可以验证对象初始化是否正确;

(2)动态关联:

定义一个指向基类shape对象的指针变量pt ,使它先后指向3个派生类对象point,circle和cylinder,然后通过指针调用个函数,如pt->shapeName(),pt->area(),pt->volume().这时是通过动态关联分别确定应该调用那个函数。分别输出不同类对象的信息。

抽象基类结论:

(1)一个基类如果包含一个或一个以上纯虚函数,就是抽象基类。抽象基类不能也不必要定义对象;

(2)一般并不是现实存在的对象的抽象;

(3)在类的层次结构中,顶层或最上面的几层可以是抽象基类;

(4)抽象基类是本类族的公共接口;

(5)区别静态关联和动态关联;

(6)如果在基类声明了虚函数,则在派生类中凡是在该函数中相同的函数名、函数类型、参数个数和参数类型函数,均为虚函数(无论在派生类中是否用virtual声明)。

(7)使用虚函数提高了程序的可扩展性。

输入流输出流

C++的输入输出

目 录 译者序 前言 第1章 对象的演化 1 1.1 基本概念 1 1.1.1 对象:特性+行为 1 1.1.2 继承:类型关系 1 1.1.3 多态性 2 1.1.4 操作概念:OOP程序像什么 3 1.2 为什么C++会成功 3 1.2.1 较好的C 3 1.2.2 采用渐进的学习方式 4 1.2.3 运行效率 4 1.2.4 系统更容易表达和理解 4 1.2.5 “库”使你事半功倍 4 1.2.6 错误处理 5 1.2.7 大程序设计 5 1.3 方法学介绍 5 1.3.1 复杂性 5 1.3.2 内部原则 6 1.3.3 外部原则 7 1.3.4 对象设计的五个阶段 9 1.3.5 方法承诺什么 10 1.3.6 方法应当提供什么 10 1.4 起草:最小的方法 12 1.4.1 前提 13 1.4.2 高概念 14 1.4.3 论述(treatment) 14 1.4.4 结构化 14 1.4.5 开发 16 1.4.6 重写 17 1.4.7 逻辑 17 1.5 其他方法 17 1.5.1 Booch 18 1.5.2 责任驱动的设计(RDD) 19 1.5.3 对象建模技术(OMT) 19 1.6 为向OOP转变而采取的策略 19 1.6.1 逐步进入OOP 19 1.6.2 管理障碍 20 1.7 小结 21 第2章 数据抽象 22 2.1 声明与定义 22 2.2 一个袖珍C库 23 2.3 放在一起:项目创建工具 29 2.4 什么是非正常 29 2.5 基本对象 30 2.6 什么是对象 34 2.7 抽象数据类型 35 2.8 对象细节 35 2.9 头文件形式 36 2.10 嵌套结构 37 2.11 小结 41 2.12 练习 41 第3章 隐藏实现 42 3.1 设置限制 42 3.2 C++的存取控制 42 3.3 友元 44 3.3.1 嵌套友元 45 3.3.2 它是纯的吗 48 3.4 对象布局 48 3.5 类 48 3.5.1 用存取控制来修改stash 50 3.5.2 用存取控制来修改stack 51 3.6 句柄类(handle classes) 51 3.6.1 可见的实现部分 51 3.6.2 减少重复编译 52 3.7 小结 54 3.8 练习 54 第4章 初始化与清除 55 4.1 用构造函数确保初始化 55 4.2 用析构函数确保清除 56 4.3 清除定义块 58 4.3.1 for循环 59 4.3.2 空间分配 60 4.4 含有构造函数和析构函数的stash 61 4.5 含有构造函数和析构函数的stack 63 4.6 集合初始化 65 4.7 缺省构造函数 67 4.8 小结 68 4.9 练习 68 第5章 函数重载与缺省参数 69 5.1 范围分解 69 5.1.1 用返回值重载 70 5.1.2 安全类型连接 70 5.2 重载的例子 71 5.3 缺省参数 74 5.4 小结 81 5.5 练习 82 第6章 输入输出流介绍 83 6.1 为什么要用输入输出流 83 6.2 解决输入输出流问题 86 6.2.1 预先了解操作符重载 86 6.2.2 插入符与提取符 87 6.2.3 通常用法 88 6.2.4 面向行的输入 90 6.3 文件输入输出流 91 6.4 输入输出流缓冲 93 6.5 在输入输出流中查找 94 6.6 strstreams 96 6.6.1 为用户分配的存储 96 6.6.2 自动存储分配 98 6.7 输出流格式化 100 6.7.1 内部格式化数据 101 6.7.2 例子 102 6.8 格式化操纵算子 106 6.9 建立操纵算子 108 6.10 输入输出流实例 111 6.10.1 代码生成 111 6.10.2 一个简单的数据记录 117 6.11 小结 123 6.12 练习 123 第7章 常量 124 7.1 值替代 124 7.1.1 头文件里的const 124 7.1.2 const的安全性 125 7.1.3 集合 126 7.1.4 与C语言的区别 126 7.2 指针 127 7.2.1 指向const的指针 127 7.2.2 const指针 127 7.2.3 赋值和类型检查 128 7.3 函数参数和返回值 128 7.3.1 传递const值 128 7.3.2 返回const值 129 7.3.3 传递和返回地址 131 7.4 类 133 7.4.1 类里的const和enum 133 7.4.2 编译期间类里的常量 134 7.4.3 const对象和成员函数 136 7.4.4 只读存储能力 139 7.5 可变的(volatile) 140 7.6 小结 141 7.7 练习 141 第8章 内联函数 142 8.1 预处理器的缺陷 142 8.2 内联函数 144 8.2.1 类内部的内联函数 145 8.2.2 存取函数 146 8.3 内联函数和编译器 150 8.3.1 局限性 150 8.3.2 赋值顺序 150 8.3.3 在构造函数和析构函数里隐藏行为 151 8.4 减少混乱 152 8.5 预处理器的特点 153 8.6 改进的错误检查 154 8.7 小结 155 8.8 练习 155 第9章 命名控制 157 9.1 来自C语言中的静态成员 157 9.1.1 函数内部的静态变量 157 9.1.2 控制连接 160 9.1.3 其他的存储类型指定符 161 9.2 名字空间 161 9.2.1 产生一个名字空间 162 9.2.2 使用名字空间 163 9.3 C++中的静态成员 166 9.3.1 定义静态数据成员的存储 166 9.3.2 嵌套类和局部类 168 9.3.3 静态成员函数 169 9.4 静态初始化的依赖因素 171 9.5 转换连接指定 174 9.6 小结 174 9.7 练习 174 第10章 引用和拷贝构造函数 176 10.1 C++中的指针 176 10.2 C++中的引用 176 10.2.1 函数中的引用 177 10.2.2 参数传递准则 178 10.3 拷贝构造函数 179 10.3.1 传值方式传递和返回 179 10.3.2 拷贝构造函数 182 10.3.3 缺省拷贝构造函数 187 10.3.4 拷贝构造函数方法的选择 188 10.4 指向成员的指针
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值