一、多重继承
1)子类同时拥有两个或两个以上的基类,同时继承了所有基类的属性和行为。
销售员    经理
      \  /
    销售经理
汽车 客用特性 商用特性
   \    |    /
     公共汽车
2)内存结构,按照继承表的顺序,从低到高地址一次排列各个基类子对象。将子类对象的地址隐式或者静态转换为基类指针,编译器会做地址计算,以保证基类指针的类型和其所指向的对象一致,但是重解释类型转换(reinterpret_cast)不做此计算。
3)防止名字冲突。或者由用户程序通过作用域限定解决冲突,或者借助using声明以重载的方式解决冲突,再或者通过汇聚替代,在汇聚子类中提供对产生冲突的函数的隐藏版本,并在该隐藏版本中通过正确的逻辑选择特定基类的实现。
4)钻石继承问题:公共基类子对象在最终子类对象中存在多个实例,沿着不同的继承路径所访问到的公共基类子对象可能不一样,由此导致数据不一致问题。
     A
    / \
   B   C
    \ /
     D
为了解决钻石继承问题,需要设法让公共基类子对象在最终子类对象中仅有唯一的实例,且为所有中间子类对象所共享——虚继承。

二、多态
形状:位置,绘制
矩形:宽度、高度,绘制
圆形:半径,绘制
    Shape
    /   \
Rect     Circle
如果将基类中的某个成员函数声明为虚函数,那么其子类中与该函数具有相同原型的成员函数就也成为虚函数,并对基类中的版本构成覆盖(override)。通过一个指向子类对象的基类指针,或者引用子类对象的基类引用,调用这个虚函数时,实际被调用的将是子类中的覆盖版本。这种特性被称为多态。

三、关于覆盖
1.基类中成员函数必须是虚函数。
2.子类中成员函数必须与基类中的虚函数拥有完全相同的函数名、形参表和常属性。
3.如果基类中的虚函数返回基本类型,那么子类覆盖版本的返回类型必须与基类完全相同。如果基类中的虚函数返回类类型的指针或者引用,那么子类覆盖版本的返回类型可以是基类返回类型的子类。
class X { ... };
class Y : public X { ... };
class A {
  virtual int foo (void) { ... }
  virtual X* bar (void) { ... }
};
class B : public A {
  int foo (void) { ... }
  Y* bar (void) { ... }
};
4.子类中的覆盖版本不能比基类版本抛出更多的异常。
5.子类中覆盖版本与基类版本的访控属性无关。
class A {
public:
  virtual int foo (void) { ... }
};
class B : public A {
private
  int foo (void) { ... }
};
B b;
b.foo (); // ERROR !
A* p = &b;
p -> foo (); // OK !

四、多态=虚函数+指针/引用
B b;
A a = (A)b;
a.foo (); // A::foo()
class A {
public:
  void foo (void) {
    this -> bar ();
  }
  virtual void bar (void) {
    cout << 'A' << endl;
  }
};
class B : public A {
private:
  void bar (void) {
    cout << 'B' << endl;
  }
};
int main (void) {
  B b;
  b.foo (); // B
}
class A {
public:
  A (void) {
    this -> bar ();
  }
  ~A (void) {
    this -> bar ();
  }
  virtual void bar (void) {
    cout << 'A' << endl;
  }
};
class B : public A {
private:
  void bar (void) {
    cout << 'B' << endl;
  }
};
int main (void) {
  B b; // 'A'
}

五、虚函数的实现原理——虚函数表
class A {
public:
  virtual void foo (void) { ... }
  virtual void bar (void) { ... }
};
class B : public A {
public:
  void foo (void) { ... }
};
编译器对于虚函数调用,不会根据调用者的类型生成对特定成员函数调用指令,相反生成一组特殊的指令,该组指令在运行时被执行,完成以下工作:
1)确定调用对象的真实类型;
2)从实际调用对象中获取虚函数表指针;
3)找到与所调用函数相对应的函数地址;
4)调用该函数。
——动态绑定(后期绑定)。
虚函数与普通成员函数相比,执行开销会更大,虚函数不能做内联优化。

六、纯虚函数、抽象类和纯抽象类
形如:
virtual 返回类型 函数名 (形参表) = 0;
的虚函数称为纯虚函数。
至少含有一个纯虚函数的类,称为抽象类。抽象类不能实例化对象。
除了构造函数和析构函数以外全部由纯虚函数组成类,称为纯抽象类。

七、运行时类型信息——RTTI
在运行阶段获得对象的类型信息的方法。
运算符:typeid
对象:typeinfo - name()、==、!=
支持多态。
dynamic_cast - 在多态父子类指针或引用之间转换。对于指针转换失败返回NULL,对于引用转换失败抛出bad_cast异常。

八、虚析构函数
将基类的析构函数定义为虚函数,delete一个指向子类对象的基类指针,实际被执行的就是子类的析构函数,而子类的析构函数又会自动调用基类的析构函数,从而保证子类和基类中所有的资源都被析构干净。

九、不是所有的函数都能定义为虚函数
构造函数
静态函数
全局函数

十、模板方法模式
class PDFReader {
public:
  void open (const char* file) {
    解析文本;
    this -> drawText ();
    解析矩形;
    drawRect ();
  }
  virtual void drawText (void) = 0;
  virtual void drawRect (void) = 0;
};
class PDFRender : public PDFReader {
  void drawText (void) { ... }
  void drawRect (void) { ... }
};
PDFRender pr;
pr.open ("1.pdf");

c++ 07的更多相关文章

  1. iOS系列 基础篇 07 Action动作和输出口

    iOS系列 基础篇 07 Action动作和输出口 目录:  1. 前言及案例说明 2. 什么是动作? 3. 什么是输出口? 4. 实战 5. 结尾 1. 前言及案例说明 上篇内容我们学习了标签和按钮 ...

  2. javaSE基础07

    javaSE基础07 一.static静态修饰符 用了static修饰的变量就会变成共享的属性,只会初始化一次,在内存中只存在一个,并且每个对象都可以访问,存放在方法区(数据共享区) 1.1 stat ...

  3. 《HelloGitHub月刊》第07期

    最近工作上的事比较多,<HelloGitHub>月刊第07期拖到月底才发. 本期月刊对logo和月刊的排版进行了优化,不知道大家的反馈如何,还望大家多多反馈,让<HelloGitHu ...

  4. Python array,list,dataframe索引切片操作 2016年07月19日——智浪文档

    array,list,dataframe索引切片操作 2016年07月19日——智浪文档 list,一维,二维array,datafrme,loc.iloc.ix的简单探讨 Numpy数组的索引和切片 ...

  5. 驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址

    驱动开发学习笔记. 0.07 Uboot链接地址 加载地址 和 链接脚本地址 最近重新看了乾龙_Heron的<ARM 上电启动及 Uboot 代码分析>(下简称<代码分析>) ...

  6. NPOI 导入导出excel 支持 03 07

    因为微软的office成本太高了,所以开发项目的时候电脑上没安装office,而是安装了wps.但开发语言用的是C#,所以直接调用微软的office组件是很方便的,但一方面慢,一方面成本高,所以从网上 ...

  7. Archlinux 2015.07.01 和 Windows7 双系统 安装教程

    提前在windows7下给Archlinux预留一个分区,大小最好在20G以上(根据自己硬盘情况分配). 第一步,安装前的准备 从arch官网下载最新的ISO文件archlinux-2015.07.0 ...

  8. Java虚拟机JVM学习07 类的卸载机制

    Java虚拟机JVM学习07 类的卸载机制 类的生命周期 当Sample类被加载.连接和初始化后,它的生命周期就开始了. 当代表Sample类的Class对象不再被引用,即不可触及时,Class对象就 ...

  9. AC日记——有趣的跳跃 openjudge 1.6 07

    07:有趣的跳跃 总时间限制:  1000ms 内存限制:  65536kB 描述 一个长度为n(n>0)的序列中存在“有趣的跳跃”当前仅当相邻元素的差的绝对值经过排序后正好是从1到(n-1). ...

  10. AC日记——配对碱基链 openjudge 1.7 07

    07:配对碱基链 总时间限制:  1000ms 内存限制:  65536kB 描述 脱氧核糖核酸(DNA)由两条互补的碱基链以双螺旋的方式结合而成.而构成DNA的碱基共有4种,分别为腺瞟呤(A).鸟嘌 ...

随机推荐

  1. linux下使用mutt发送带附件的邮件

    echo "hello"|mutt -s "world" -a hack.jpg -- name@address.com

  2. VMware vSphere 5.5的12个更新亮点(1)

    [IT专家网虚拟化]在VMworld 2013大会上发布的VMware vSphere 5.5版本提供的增强和改进,横跨从hypervisor到管理整个堆栈,提升了VMware的性能.可伸缩性和可用性 ...

  3. c++11: trailing return type in functions(函数返回类型后置)

    In C++03, the return type of a function template cannot be generalized if the return type relies on ...

  4. aspx生成验证码

    //定义方法 public partial class VerificationCode : System.Web.UI.Page    {        string ImagePath = &qu ...

  5. (转)Javascript面向对象编程(三):非构造函数的继承(作者:阮一峰)

    不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { na ...

  6. iPhoneKeyboard

    iPhoneKeyboard.Open static function Open (text : string, keyboardType : iPhoneKeyboardType = iPhoneK ...

  7. String.equals()

    名称                                               说明 String.Equals(Obejecct)            确定String实例是否指 ...

  8. uva11426 欧拉函数应用

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=121873#problem/F 题目大意:给你一个数n,让你输出(i=1-> ...

  9. Codeforces round #353div2 C

    题目来源:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=117863#problem/C 题目大意:给你n个数字,代表这个人在n个银行里面 ...

  10. VC++下使用SQLite数据库

    老师最近给的上机题目有点变态,特别是写到最后,是需要写学生管理系统.如果C语言结合文件来操作的话,估计会比较麻烦(对文件里字符串的增删改查我都没有什么好点的算法).那就用数据库吧,我很自然的想到. 前 ...