1.除了构造函数之外,任意非static成员函数都可以是虚函数。保留字virtual只在类内部的成员函数声明处出现,不能用在类定义体外部出现的函数定义上。

2.派生类只能通过派生类对象访问其基类的protected成员,派生类对其基类类型对象的protected成员没有特殊访问权限。

3.派生类中虚函数的声明必须与基类中的定义方式完全匹配,但有一个例外:返回对基类的引用(或指针)的虚函数。派生类中的虚函数可以返回基类函数所返回类型的派生类的引用(或指针)。

4.因为每个派生类对象都有基类部分,类可以访问其基类的public和protected成员,就好像那些成员是派生类自己的成员一样。

5.要触发动态绑定,必须满足两个条件:
(1)只有指定为虚函数的成员函数才能进行动态绑定

(2)必须通过基类类型的引用或指针进行函数调用。

6.引用和指针的静态类型与动态类型可以不同,这是C++用以支持多态性的基石。

如果调用非虚函数,则无论实际对象是什么类型,都执行基类类型所定义的函数。如果调用虚函数,则直到运行时才能确定调用哪个函数,运行的虚函数是引用所绑定的或指针所指向的对象所属类型定义的版本。

7.如果虚函数有默认实参,通过基类的引用或指针调用虚函数时,默认实参为基类虚函数声明中指定的值,但是调用的是派生类的虚函数。

8.使用class保留字定义的派生类默认具有private继承,而用struct保留字定义类默认具有public继承。

classBase{ /*.....*/ };
structD1:Base{ /*.....*/}; //publicinheritanceby default classD2:Base{ /*.....*/}; //privateinheritance by default

9.友元关系不能继承。基类的友元对派生类的成员没有特殊访问权限。如果基类被授予友元关系,则只有基类具有特殊访问权限,该基类的派生类不能访问授予友元关系。

classBase
{
friend class Frnd;
protected:
int i;
}; classD1:public Base
{
protected:
int j;
}; classFrnd
{
public:
int mem(Base b) { returnb.i; } //OK:Frnd is friend to Base
int mem(D1 d) { return d.i;} //error:friendship doesn'tinherit
}; classD2:public Frnd
{
int mem(Base b) { return b.i;}//error:friendship doesn't inherit
};

10.如果基类定义了static成员,则整个继承层次中只有一个这样的成员。无论从基类派生出多少个派生类,每个static成员只有一个实例。

static成员遵循常规访问控制:如果成员在基类中为private,则派生类不能访问它。假定可以访问成员,则既可以通过基类访问static成员,也可以通过派生类访问static成员。

11.派生类合成的默认构造函数与非派生的构造函数只有一点不同:除了初始化派生类的数据成员之外,它还初始化派生类对象的基类部分。基类部分由基类的默认构造函数初始化。(初始化顺序:先调用基类的默认构造函数,再初始化派生类的成员。

12.只包含类类型或内置数据类型数据成员、不含指针的类一般可以使用合成操作,复制、赋值或撤销这样的成员函数不需要特殊控制。具有指针成员的类一般需要定义自己的复制控制来管理这些成员。

13.如果派生类显式定义自己的复制构造函数或赋值构造操作符,则该定义将完全覆盖默认定义。派生类的复制构造函数和赋值操作符负责对基类成分以及类自己的成员进行复制或赋值。

如果派生类定义了自己的复制构造函数,该复制构造函数一般应显式使用基类复制构造函数初始化对象的基类部分:

classBase { /*.....*/ };
classDerived: public Base
{
public:
Derived(const Derived& d):
Base(d) /*other memberinitialization*/
{ /*....*/ }
};

初始化函数Base(d)将派生类对象d转换为它的基类部分的引用,并调用基类复制构造函数。如果省略基类初始化函数,如下代码:

Derived(constDerived& d) /*derived member initializations*/
{/*....*/ }

效果是运行Base的默认构造函数初始化对象的基类部分。假定Derived成员的初始化从d复制对应成员,则新构造的对象将具有奇怪的配置:它的Base部分讲保存默认值,而它的Derived成员是另一个对象的副本。

14.赋值操作符通常与复制构造函数类似:如果派生类定义了自己的赋值操作符,则该操作符必须对基类部分进行显式赋值。

Derived&Derived::operator=(constDerived &rhs)
{
if ( this != &rhs )
Base::operator=(rhs);
return *this;
}

15.如果派生类中的拷贝和赋值构造函数中没有“显式指定基类的拷贝和赋值构造函数”,即派生类只是把自己的成员进行了赋值,基类部分是调用基类的默认构造函数。

16.对象、引用或指针的静态类型决定了对象能够完成的行为。甚至当静态类型和动态类型可能不同的时候,就像使用基类类型的引用或指针时可能会发生的,静态类型仍然决定着可以使用什么成员。

17.在基类和派生类中使用同一个名字的成员函数,其行为与数据成员一样:在派生类作用域中派生类成员将屏蔽基类成员。即使函数原型不同,基类成员也会被屏蔽。

18.确定函数调用遵循以下四个步骤(注意顺序):

(1)首先确定进行函数调用的对象、引用或指针的静态类型。

(2)在该类中查找函数,(只要函数名相同就行,函数原型不管)如果找不到,就在直接基类中查找,如此遵循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关基类中找到该名字,则调用时错误的。

(3)一旦找到了该名字,就进行常规类型检查,查看如果给定找到的定义,该函数调用是否合法。

(4)假定函数调用合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成代码直接调用函数。

19.将函数定义为纯虚函数能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类中的版本决不会调用。试图创建抽象基类的对象将发生编译时错误。

含有(或继承)一个或多个纯虚函数的类似抽象基类。除了作为抽象基类的派生类的对象的组成部分,不能创建抽象类型的对象。

C++ Primer 有感(面向对象编程)的更多相关文章

  1. C++ Primer 学习笔记_67_面向对象编程 --转换与继承、复制控制与继承

    面向对象编程 --转换与继承.复制控制与继承 I.转换与继承 引言: 由于每一个派生类对象都包括一个基类部分,因此能够像使用基类对象一样在派生类对象上执行操作. 对于指针/引用,能够将派生类对象的指针 ...

  2. c++primer复习(六)—面向对象编程

    1 C++中,通过基类的引用(或指针)调用虚函数时,发生动态绑定,两个条件(基类引用或指针.虚函数)缺一不可 虚函数的默认实参将发生静态绑定 2 继承层次的根类一般都需要定义虚析构函数 3 任意非st ...

  3. C++ Primer 学习笔记_69_面向对象编程 --继承情况下的类作用域

    面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:假设不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这样的类作用域的层次嵌套使 ...

  4. 《C++ Primer》之面向对象编程(四)

    纯虚函数 在前面所提到过的 Disc_item 类提出了一个有趣的问题:该类从 Item_base 继承了 net_price 函数但没有重定义该函数.因为对 Disc_item 类而言没有可以给予该 ...

  5. 《C++ Primer》之面向对象编程(一)

    面向对象编程基于三个基本概念:数据抽象.继承和动态绑定.//动态绑定使编译器能够在运行时决定是使用基类中定义的函数还是派生类中定义的函数. 面向对象编程的关键思想是多态性(polymorphism). ...

  6. <C++Primer>第四版 阅读笔记 第四部分 “面向对象编程与泛型编程”

    继承和动态绑定与数据抽象一起成为面向对象编程的基础. 模板使我们能够编写独立于具体类型的泛型类和泛型函数. 第15章 面向对象编程 面向对象编程基于三个基本概念:数据抽象.继承和动态绑定.在C++中, ...

  7. C++ Primer 学习笔记_72_面向对象编程 --句柄类与继承[续]

    面向对象编程 --句柄类与继承[续] 三.句柄的使用 使用Sales_item对象能够更easy地编写书店应用程序.代码将不必管理Item_base对象的指针,但仍然能够获得通过Sales_item对 ...

  8. C++ Primer(第4版)-学习笔记-第4部分:面向对象编程与泛型编程

    第15章 面向对象编程OOP(Object-oriented programming)           面向对象编程基于三个基本概念:数据抽象.继承和动态绑定.      在 C++ 中,用类进行 ...

  9. C++ 面向对象编程

    <C++ Primer 4th>读书笔记 面向对象编程基于三个基本概念:数据抽象.继承和动态绑定.在 C++ 中,用类进行数据抽象,用类派生从一个类继承另一个:派生类继承基类的成员.动态绑 ...

  10. 泛型编程、STL的概念、STL模板思想及其六大组件的关系,以及泛型编程(GP)、STL、面向对象编程(OOP)、C++之间的关系

    2013-08-11 10:46:39 介绍STL模板的书,有两本比较经典: 一本是<Generic Programming and the STL>,中文翻译为<泛型编程与STL& ...

随机推荐

  1. python--ftp服务器(pyftpdlib)

    # -*- coding: utf-8 -*-# @Time : 2018/4/11 16:47# @Author : liuxiaobing# @File : test2.py# @Software ...

  2. spring web项目下,判断项目是否启动完成

    本文同时发布于见鬼网:https://faceghost.com/article/483341 概述:spring 加载完成后,我们有时候会做一些初始化工作,如加载一些缓存,DB,等,这里采用实现Se ...

  3. html css <input> javaScript .数据类型 JS中的函数编写方式 BOM总结 DOM总结

    Day27  html css div 块标签. 特点: 独占一行,有高度和宽度 span 行元素. 特点:在同一行显示,当前行满了自动去下一行显示. 不识别高度和宽度 1.1.1.1 2.输入域标签 ...

  4. java.lang.ClassCastException: oracle.sql.CLOB cannot be cast to oracle.sql.CLOB

    错误现象: [framework] 2016-05-26 11:34:53,590 -INFO  [http-bio-8080-exec-7] -1231863 -com.dhcc.base.db.D ...

  5. delphi 线程教学第四节:多线程类的改进

    第四节:多线程类的改进   1.需要改进的地方   a) 让线程类结束时不自动释放,以便符合 delphi 的用法.即 FreeOnTerminate:=false; b) 改造 Create 的参数 ...

  6. Java不走弯路教程(3.用户验证与文件内容查询)

    3.用户验证与文件内容查询 在上一章中,我们完成了对指定文件内容的输出操作. 我们现在有如下格式的文件product.db id,product_name,product_detail 1,noteb ...

  7. Docker 删除容器

    可以使用 docker rm 来删除一个处于终止状态的容器. 例如 $sudo docker rm trusting_newton trusting_newton 如果要删除一个运行中的容器,可以添加 ...

  8. C++格式化输出浮点数

    主要内容 介绍C++中如何格式化输出浮点数. 控制浮点数输出格式需要包含iomanip头文件. 使用fixed来控制输出的浮点数的小数位是固定的.可参考http://en.cppreference.c ...

  9. [Gradle系列]Gradle发布module库到jCenter, 并构建自己的企业Maven私服

    Tamic 作者: http://blog.csdn.net/sk719887916/article/details/53224544 前言 andorid开发者经常会看到xx公司发布了xx项目,xx ...

  10. linux下安装apache(httpd-2.4.3版本)各种坑

    博主的linux是ubuntu 14.04.3. 在安装apache最新版httpd-2.4.3的时候遇到各种坑. 先提供安装apache httpd-2.4.3所需要的包,博主已经整理好,下载地址: ...