C++Primer 第十五章
//1.面向对象程序设计的核心思想是数据抽象,继承,动态绑定。
// 通过使用数据抽象,我们可以将类的接口和实现分离
// 使用继承,可以定义相似的类型并对其相似关系建模
// 使用动态绑定,可以在一定程度上忽视相似类型的区别,而以统一的方式使用它们的对象。 //2.对于某些函数,基类希望它的派生类各自定义适合自身的版本,此时基类就将这些函数声明为虚函数。
// 使用基类的引用或指针调用一个虚函数的时候,将发生动态绑定:根据指针或引用指向的对象类型来调用基类或者派生类的虚函数。
// 基类通常定义一个虚析构函数,以便于对象的正常析构
// 任何构造函数之外的非静态函数都可以是虚函数。在基类中的虚函数,在派生类中隐式的也是虚函数。
// 成员函数如果没有被声明为虚函数,则其解析过程发生在编译时而非运行时。
// 每个类控制自己成员的初始化过程,派生类也最好使用基类的构造函数来初始化它的基类部分 //3.可以将基类的指针或引用绑定到派生类对象上有一层极为重要的含义:当使用基类类型的指针或引用的时候,实际上不清楚其所绑定对象的真实类型。
// 派生类向基类的转换只对指针和引用类型有效,在派生类类型和基类类型之间不存在这样的转换。 //4.智能指针类也支持派生类向基类的转换,这意味着可以将派生类的对象的指针存储在一个基类的智能指针内。 //5.一个派生类如果要覆盖而非隐藏某个继承的虚函数,则它的形参类型必须和被覆盖的虚函数完全一致。
// 同样的,它们的返回类型也必须一致。对于这个规则有一个例外:当此函数返回其类类型的指针或引用时,并且子类向父类类型转换时可访问的时候,它们可以返回各自的类类型。 //6.虚函数也可以有默认实参,但是如果某次函数调用使用了默认实参,则该实参值由本次调用的静态类型决定。所以虚函数最好不用默认实参,或者在子类和基类中使用相同的默认实参。
// 通过作用域运算符,可以实现对虚函数的调用不进行动态绑定。 //7.抽象基类:
// A:和普通的虚函数不同,一个纯虚函数可以没有定义,通过在函数体的位置书写=0就可以将一个虚函数声明为纯虚函数,=0只能出现在类内部虚函数声明处。
// B:也可以为纯虚函数提供定义,但是必须是在类的外部。
// C:不能定义抽象基类的对象,当抽象基类的派生类没有覆盖纯虚函数时,此派生类也不能定义对象。 //8.派生类的构造函数只初始化它的直接基类。各个类控制其对象的初始化过程。 //9.派生类向基类转换的可访问性:
// A:只有当D公有的继承B时,用户代码才能使用派生类向基类的转换。
// B:不论D以任何方式继承B,D的成员函数和友员都能使用派生类向基类的转换。
// C:如果D继承B的方式是公有的或受保护的,则D类的派生类的成员和友员可以使用D向B的类型转换。
// 总结:对于代码中的某个节点来说:如果基类的公有成员是可访问的,则派生类向基类的转换也是可使用的,反之则不行。 //10.就像友员关系不能传递一样,友员关系同样不能继承。基类的友员在访问派生类成员时不具有特殊性,类似的,派生类的友员也不能随意访问基类的成员。 //11.派生类可以为那些可访问的名字提供using声明,以此方法来改变被声明的名字的访问权限(具体权限取决于using声明的位置)。
class CA {protected: int value;};
class CB : public CA {public: using CA::value;}; //则value在CB类中的访问权限是public的 //12.struct和class的唯一区别在于:默认成员访问说明符及默认派生访问说明符的区别,前者均为公有,后者均为私有。 //13.每个类定义了自己的作用域。当存在继承关系时,派生类的作用域嵌套在其基类的作用域中。当一个名字在派生类的作用域中无法被解析,则编译器将在其外层的基类作用域中进行查找。
// 正是由于上述规定,所以在派生类中才能像使用自己的成员一样使用基类的成员。
// 一个对象、指针、引用的静态类型决定了该对象的哪些成员是可见的。即使静态类型和动态类型可能不一致,但是我们能使用哪些成员仍旧是由其静态类型决定的。 //14.和其它作用域一样,派生类也能重用定义在其直接或间接基类中的名字,此时将发生隐藏,派生类的成员将隐藏同名的基类成员,可以通过作用域运算符来访问被隐藏的成员。
// 由于上述隐藏的规则,派生类可以覆盖其基类的重载虚函数的0个或者全部版本,若非如此将发生隐藏。这样就会显得和繁琐。
// 对于上述问题,一个很好的解决方法是:为重载的成员提供一条using声明语句,这样我们就可以无需覆盖基类中的每一个重载版本。此时派生类只需要定义其特殊的函数语句即可。
class CA
{
public:
virtual void fun(){printf("A_0");}
virtual void fun(int){printf("A_1");}
virtual void fun(char*){printf("A_2");}
};
class CB : public CA
{
public:
using CA::fun; //使基类中的所有fun函数被添加到派生类的作用域中。
void fun(int i){printf("B_1");} //重新定义派生类中特定的虚函数。
}; //15.继承关系对基类拷贝控制最直接的影响就是基类通常应该定义一个虚析构函数来正确的释放对象。
// 基类或派生类的合成拷贝控制成员对类本身的成员依次进行初始化、赋值、销毁的操作,此外这些合成的成员还负责使用直接基类中对应的操作对一个对象的直接基类部分进行相应操作。// 在实际编程过程中,如果基类中没有默认、拷贝、移动构造函数,则派生类一般也不要定义相应的操作,其原因是派生类的基类部分将无法被正确操作。 //16.当我们用一个派生类对象为其基类对象初始化或赋值的时候,只有该派生类对象的基类部分会被拷贝、移动、赋值,它的派生类部分将被忽略掉。
//17.
A(基类) B(派生类)
公有继承 公有成员 公有成员
保护成员 保护成员
私有成员 不可见
保护继承 公有成员 保护成员
保护成员 保护成员
私有成员 不可见
私有继承 公有成员 私有成员
保护成员 私有成员
私有成员 不可见
一般来说,公有继承时是Is A的关系,私有继承时是Has A的关系
C++Primer 第十五章的更多相关文章
- C++ Primer Plus学习:第十五章
第十五章 友元.异常和其他 友元 友元类 表 0-1 class Tv { public: friend class Remote; } Remote类可以使用Tv的数据成员,Remote类在Tv类后 ...
- 【C++】《C++ Primer 》第十五章
第十五章 面向对象程序设计 一.OOP:概述 面向对象程序设计(OOP)的核心思想是数据抽象.继承和动态绑定. 通过使用数据抽象,可以将类的接口和实现分离. 使用继承,可以定义相似的类型并对其相似关系 ...
- 15第十五章UDF用户自定义函数(转载)
15第十五章UDF用户自定义函数 待补上 原文链接 本文由豆约翰博客备份专家远程一键发布
- 《Linux命令行与shell脚本编程大全》 第十五章 学习笔记
第十五章:控制脚本 处理信号 重温Linux信号 信号 名称 描述 1 HUP 挂起 2 INT 中断 3 QUIT 结束运行 9 KILL 无条件终止 11 SEGV 段错误 15 TERM 尽可能 ...
- CSS3秘笈复习:十三章&十四章&十五章&十六章&十七章
第十三章 1.在使用浮动时,源代码的顺序非常重要.浮动元素的HTML必须处在要包围它的元素的HTML之前. 2.清楚浮动: (1).在外围div的底部添加一个清除元素:clear属性可以防止元素包围浮 ...
- Gradle 1.12用户指南翻译——第四十五章. 应用程序插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- Gradle 1.12 翻译——第十五章. 任务详述
有关其他已翻译的章节请关注Github上的项目:https://github.com/msdx/gradledoc/tree/1.12,或访问:http://gradledoc.qiniudn.com ...
- Gradle 1.12用户指南翻译——第二十五章. Scala 插件
其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...
- Gradle 1.12用户指南翻译——第三十五章. Sonar 插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
随机推荐
- NERDTree 快捷键辑录
参看连接:http://www.cnblogs.com/lexus/archive/2012/11/04/2753187.html http://yang3wei.github.io/blog/201 ...
- Apache Kafka源码分析 - ReplicaStateMachine
startup 在onControllerFailover中被调用, /** * Invoked on successful controller election. First registers ...
- JS中基本window.document对象操作以及常用事件!
一.找到元素 1.document.getELementById("id"):根据id找,最多找一个. var a=document.getELementById("id ...
- 修改MyEclipse默认的Servlet和jsp代码模板
一.修改Servlet的默认模板代码 使用MyEclipse创建Servlet时,根据默认的Servlet模板生成的Servlet代码如下: 1 package gacl.servlet.study; ...
- 转一个 C#基础类库
转自:http://www.cnblogs.com/sufei/archive/2012/12/07/2807170.html http://www.sufeinet.com/thread-655-1 ...
- This system is not registered with RHN
在红帽EL5上运行yum,提示“This system is not registered with RHN”,意思是没有在官网上注册,不能下载RH的软件包,替代方案是采用centos源. 1.卸载r ...
- 在express中使用Mongoose连接MongoDB
为何要学Mongoose? Mongoose是MongoDB的一个对象模型工具,封装了MongoDB对文档的的一些增删改查等常用方法,让NodeJS操作Mongodb数据库变得更加灵活简单. 0.安装 ...
- Dreamweaver代码提示快捷键冲突
平时习惯使用Ctrl+空格进行输入法的切换,然后Dreamweaver代码提示的快捷键也是Ctrl+空格,那么只好把Dw的快捷键改掉吧, 选择菜单:编辑->快捷键 复制副本 选择编辑 找到&qu ...
- threading多线程
什么是线程? 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.一 ...
- EntityFramework执行SQL语句
在EF中执行Sql语句. using (var context = new EFRecipesEntities()) { string sql = @"insert into Chapter ...