1.继承方式

三种继承方式,public,private,protected。注意,继承方式是相对于某一层类的方法而言,并不是相对于子类的对象而言。对于外部世界()对象来说,protected和private相似。对于派生类来说,protected和public相似。

public继承。派生类中,父类public和protected的成员可以直接访问,仍旧保持public属性。派生类对象,父类public成员可以访问。

private继承。派生类中,父类public和protected的成员可以直接访问,但是已经成为了private属性。直接后果:其一是派生类对象不能直接访问这些成员了(类外私有);其二、派生类的子类也不能直接访问这些成员了(已经私有属性,只能经由该层派生类访问)。

protected继承。派生类中,父类public和protected的成员可以直接访问,但是已经成为了protected属性。直接后果:派生类对象不能不能直接访问这些成员了(私有),同样派生类的子类可以继访问(protected)。

总结而言:

基类中     继承方式         子类中

public & public继承 => public

public & protected继承 => protected

public & private继承 = > private

protected & public继承 => protected

protected & protected继承 => protected

protected & private继承 = > private

private & public继承 => 子类无权访问

private & protected继承 => 子类无权访问

private & private继承 = > 子类无权访问

2.虚继承

虚继承时为了解决多重继承出现的钻石继承导致子对象重复。虚继承可以节省内存。当然节省了内存牺牲了时间。相较于普通继承而言,虚继承:

(1)时间上在通过继承类对象访问虚基类对象中的成员(包括数据成员和函数成员)时,都必须通过某种间接引用来完成,这样会增加引用寻址时间(就和虚函数一样),其实就是调整this指针以指向虚基类对象,只不过这个调整是运行时间接完成的。

(2)空间上由于共享所以不必要在对象内存中保存多份虚基类子对象的拷贝,这样较之多继承节省空间(避免了同时出现两个基类子对像)。在虚拟继承情况下,基类子对象的布局是不同于普通继承的。因此,它需要多出一个指向基类子对象的指针。

      考虑以下情况:

分别求sizeof(a),sizeof(b)。结果为:

                第一种:4,12 

                第二种:4,4

                第三种:8,16

                第四种:8,8

     分析

考虑a: 涉及到内存对齐(由于每一个类均有虚函数,每个对象隐含保存虚指针指向类虚函数表,大小占4),故a的大小很好判断。

      考虑b: 实际上:
             第一个:vfptr(b:foo)+vbptr+vfptr(a:func)=12
             第二个:vfptr(a:func, b:foo)=4
             第三个:vfptr(b:foo)+vbptr+vfptr(a:func)+x(对齐为四个字节)=16
             第四个:vfptr(a:func, b:foo)+x(对齐为四个字节)=8

含有虚函数的类均有指向自身虚函数表的虚指针。只是虚继承时,虚函数表仅有自身的虚函数地址,而非虚函数,且每一层的虚指针都存在,且派生类包括一个指向父类对象的虚指针。对于非虚继承,始终有且仅有一个虚指针,且包含所有虚函数地址。

同样

class A{
char k[3];
public :
virtual void a(){};
};
class B1:public virtual A{
char k[3];
public :
virtual void b(){};
};
class C1:public virtual B1{
char k[3];
public :
virtual void c(){};
}; class B2:public A{
char k[3];
public :
virtual void b(){};
};
class C2:public B2{
char k[3];
public :
virtual void c(){};
};

A B1 C1 大小为8 20 32

A B2 B1 大小为8 12 16

3.重载、覆盖、隐藏的区别

重载:类内重载,同名不同参数。注意,虚函数也可以有包含重载类型,此时派生类必须对所有重载类型再次定义。

        覆盖:派生覆盖,即派生类函数覆盖基类函数,同名同参且为虚函数。即虚函数机制属于覆盖类型。

        隐藏:派生隐藏,即派生类的函数屏蔽了基类函数,同名不要求参数。虚函数也存在隐藏现象,即派生类存在同名不同参数的虚函数,会导致基类同名虚函数被隐藏。

4.虚指针与虚函数表

(1)虚(函数)指针用于虚函数的实现细节,带虚函数的类的每一个对象都有一个虚指针指向该类的虚函数列表。

(2)每个虚函数都在虚函数表占有一个地址。派生类对象包含指向独立地址表的指针。若提供了虚函数的新定义,则虚函数表保持性函数的地址,否则保留父类虚表的地址。

(3)不论类中有多少虚函数。类的对象只有一个虚函数指针指向该类的虚表。

(4)使用虚函数时。每个对象存储都增大,即包含指针存储空间(通常4字节)。每个虚函数调用,都需要执行地址查找。

参考:

1.关于C++中的虚拟继承的一些总结

C++的继承与接口的更多相关文章

  1. Javascript面向对象特性实现封装、继承、接口详细案例——进级高手篇

    Javascript面向对象特性实现(封装.继承.接口) Javascript作为弱类型语言,和Java.php等服务端脚本语言相比,拥有极强的灵活性.对于小型的web需求,在编写javascript ...

  2. C#类继承和接口继承时一些模棱两可的问题[转]

    原文地址:http://www.cnblogs.com/harleyhu/archive/2012/11/29/2794809.html 1.在father定义的方法若含有virtual关键字,chi ...

  3. Java继承和接口

    接口最关键的作用,也是使用接口最重要的一个原因:能上溯造型至多个基础类.使用接口的第二个原因与使用抽象基础类的原因是一样的:防止客户程序员制作这个类的一个对象,以及规定它仅仅是一个接口.这样便带来了一 ...

  4. 基础学习day07---面向对象三---继承,接口与 抽象类

    一.继承 1.1.继承概念 将对象的共性抽取出来.提取出一个单独的类. 继承使用复用以前的代码非常容易,能够大大的缩短开发周期,降低开发成本,同时增加程序的易维护性 继承使重一个类A能够直接使用另外一 ...

  5. java 类的继承和接口的继承

    父类 public class person { String name; int age; void eat(){ System.out.println("吃饭"); } voi ...

  6. Effective C++ 笔记:条款 34 实现继承和接口继承

    Differentiate between inheritance of interface and inheritance of implementation. 行为含义 声明一个pure virt ...

  7. 【C# 复习总结】类、继承和接口

    1 类 定义新的数据类型以及这些新的数据类型进行相互操作的方法 定义方式: class Cat { } class Cat:object { } C#中所有的类都是默认由object类派生来的,显示指 ...

  8. Javascript面向对象特性实现封装、继承、接口详细案例

    Javascript面向对象特性实现(封装.继承.接口) Javascript作为弱类型语言,和Java.php等服务端脚本语言相比,拥有极强的灵活性.对于小型的web需求,在编写javascript ...

  9. java基础知识总结--继承和接口

    什么是继承?什么是接口?他们之间的区别和联系是什么? 什么是继承? 继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能.多个类中存在相同属性和行 ...

  10. PHP接口继承及接口多继承原理与实现方法详解

    在PHP的接口中,接口可以继承接口.虽然PHP类只能继承一个父类(单继承),但是接口和类不同,接口可以实现多继承,可以继承一个或者多个接口.当然接口的继承也是使用extends关键字,要多个继承的话只 ...

随机推荐

  1. RocketMQ原理讲解系列文章

    [RocketMQ原理解析][http://blog.csdn.net/quhongwei_zhanqiu/article/category/2548637] [消息的可靠性.顺序和重复][https ...

  2. Django-03

    知识预览 分页器(paginator) COOKIE 与 SESSION Django的用户认证 FORM 回到顶部 分页器(paginator) 分页器的使用 1 2 3 4 5 6 7 8 9 1 ...

  3. C++循环链表实现约瑟夫退圈(类封装)

    node.h #pragma once #include <iostream> #include <iomanip> using namespace std; struct n ...

  4. 分布式_理论_04_ 3PC

    一.前言 五.参考资料 1.分布式理论(四)—— 一致性协议之 3PC 2.分布式理论(四) - 3PC协议 3.

  5. python any函数

    pyhton的any() 函数: 判断给定的可迭代参数 iterable : 全部为 False,返回 False; 至少有一个为 True,则返回 True. 元素除了是 0.空.FALSE 外都算 ...

  6. Java VM(虚拟机) 参数

    -XX:PermSize/-XX:MaxPermSize,永久代内存: 1. 虚拟机参数:-ea,支持 assert 断言关键字 eclipse 默认是不开启此参数的,也就是虽然编译器支持 asser ...

  7. docker下安装 Oracle11gR2

    这是第二次安装,在第一次安装过程部分内容参考自如下: http://blog.sina.com.cn/s/blog_d840ff330102v4j0.html docker下oracle11g安装 h ...

  8. Cow Exhibition (背包中的负数问题)

    个人心得:背包,动态规划真的是有点模糊不清,太过于抽象,为什么有些是从后面递推, 有些状态就是从前面往后面,真叫人头大. 这一题因为涉及到负数,所以网上大神们就把开始位置从10000开始,这样子就转变 ...

  9. MLCC 电容的的 NP0 C0G 材质

    MLCC 电容的的 NP0 C0G 材质 随手记一下. MLCC 中最稳定的材质 NP0 C0G,NP0 和 C0G 是相同的,只是不同的产商不同的名字而已. 注意中间的是 0 不是 英文字母 O,虽 ...

  10. python面向对象-我的理解

    参考:博客 Vamei .廖雪峰 面向对象概念 面向对象完全可以按照自然界生物分类法来理解. 当然,它不会有自然界那么复杂. 因为我专业的关系,因此个人觉得微生物来举例很容易理解. 所有的微生物都具有 ...