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. Ubuntu16.04下安装jdk1.8过程

    笔者环境:腾讯云服务器 Ubuntu16.04 x64 一 . 去oracle官网下载对应的jdk 下载地址:http://www.oracle.com/technetwork/java/javase ...

  2. 含有分类变量(categorical variable)的逻辑回归(logistic regression)中虚拟变量(哑变量,dummy variable)的理解

    版权声明:本文为博主原创文章,博客地址:,欢迎大家相互转载交流. 使用R语言做逻辑回归的时候,当自变量中有分类变量(大于两个)的时候,对于回归模型的结果有一点困惑,搜索相关知识发现不少人也有相同的疑问 ...

  3. CRM客户关系管理系统(七)

    第七章.动态modelform功能实现  7.1.动态modelform的实现 (1)给第一列添加一个a标签 kingadmintag.py (2)kingadmin/urls.py urlpatte ...

  4. Elastic-Job——分布式定时任务框架

    摘要: Elastic-Job是ddframe中dd-job的作业模块中分离出来的分布式弹性作业框架.去掉了和dd-job中的监控和ddframe接入规范部分.该项目基于成熟的开源产品Quartz和Z ...

  5. Dynamics 365 Web Api之基于single-valued navigation property的filter查询

    本篇要讲的是dynamics 新版本中web api的一个改进功能,虽然改进的很有限,但至少是改进了. 举个例子,我们现在知道联系人的名字vic,我们想找出客户记录中主要联系人名字为vic的所有客户, ...

  6. Rails多路径调用相同方法原路返回的方法

    有时候可能有多条path到达同一个method,此时,我们希望在该方法完成后自动转到之前进入的path中去,其实实现起来非常简单,只需要实现如下两个方法: def redirect_back_or(d ...

  7. SpringBatch简介

    spring Batch是一个轻量级的.完善的批处理框架,旨在帮助企业建立健壮.高效的批处理应用.SpringBatch是Spring的一个子项目,使用Java语言并基于Spring框架为基础开发,使 ...

  8. 20160216.CCPP体系详解(0026天)

    程序片段(01):01.MemCpy.c 内容概要:内存拷贝 #include <stdio.h> #include <stdlib.h> #include <memor ...

  9. Spark-SQL之DataFrame操作大全

    Spark SQL中的DataFrame类似于一张关系型数据表.在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现.可以参考,Scala提供的DataFra ...

  10. Android开发使用Java8新特性

    Android 支持所有 Java 7 语言功能,以及一部分 Java 8 语言功能(具体因平台版本而异).本文介绍您可以使用的新语言功能.如何正确配置项目以使用这些功能,以及您可能遇到的任何已知问题 ...