在学习设计模式时我就有一个疑问,关联和继承除了用法上的区别,好像在内存上并没有什么区别,继承也是父类作为了子类的元素(内存上),关联也是这样。而且关联好像更占内存一些。这就是设计模式里问题了“依赖倒转原则”。

继承分为public继承,protect继承,private继承

public:父类中的public,protected成员到了派生类中属性不变。

protected:父类中的public,protected成员到了派生类中,都变为protected成员。

private:父类中的public,protected成员到了派生类中,都变成了private成员。

特别注意:父类中的private成员是不会被继承到子类中的(这也是关联和继承的一个区别)。

特别注意:还有一种继承被称为虚继承

详细回顾一下虚继承:

虚继承的形式:

class 派生类:virtual public 基类1,virtual public 基类2, virtual public 基类3……

{
};

构造函数过程:

首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;

执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;

执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;

执行派生类自己的构造函数;

析构以与构造相反的顺序执行;

虚继承的实质是,在多继承中,派生类的基类中如果有过个基类继承至同一基类,那么这几个基类肯定含有这同一基类的拷贝(各自各一份),所以在派生类中如果想使用,就必须加上作用域分辨符来唯一识别。这时如果另这些基类继承时用上虚基类就可以解决这个问题了。我们可以将共同继承的基类,设为虚基类,这时从不同路径继承过来的同名的数据成员在内存中就只有一份拷贝, 同名函数也只有一个映射。

 #include<iostream>

 using namespace std;

 class Base
{
private:
int val;
public:
Base(){ cout << "Base无参构造函数" << endl; };
Base(int val){ this->val = val; cout << "Base有参构造函数" << endl; }
void print(){ cout << "val = "<<val << endl; }
}; class Sub1 :virtual public Base
{
public :
Sub1(int val) :Base(val){ cout << "Sub1含参构造函数" << endl; };
}; class Sub2 :virtual public Base
{
public:
Sub2(int val) :Base(val){ cout << "Sub2含参构造函数" << endl; }
}; class Child :public Sub1, public Sub2
{
public :
Child(int val) :Sub1(val), Sub2(val){ cout << "Child含参构造函数" << endl; }
}; int main()
{
Child child();
child.print();
}

输出结果:

Base无参构造函数
Sub1含参构造函数
Sub2含参构造函数
Child含参构造函数
val = -858993460
Press any key to continue . . .

可见Sub1,和Sub2构造函数并没有执行Base的构造函数,虚继承的构造函数是这样的,先执行虚基类的无参构造函数,然后在执行Sub1的构造函数,在执行Sub2的构造函数,在执行Child的构造函数,并且在执行Sub1和Sub2的构造函数时并不再执行Base的构造函数。

如果不用虚继承的访问方式:

 #include<iostream>

 using namespace std;

 class Base
{
private:
int val;
public:
Base(){ cout << "Base无参构造函数" << endl; };
Base(int val){ this->val = val; cout << "Base有参构造函数" << endl; }
void print(){ cout << "val = "<<val << endl; }
}; class Sub1 :public Base
{
public :
Sub1(int val) :Base(val){ cout << "Sub1含参构造函数" << endl; };
}; class Sub2 :public Base
{
public:
Sub2(int val) :Base(val){ cout << "Sub2含参构造函数" << endl; }
}; class Child :public Sub1, public Sub2
{
public :
Child(int val) :Sub1(val), Sub2(val){ cout << "Child含参构造函数" << endl; }
}; int main()
{
Child child(); //child.print() //非法的访问 child.Sub1::print();
child.Sub2::print();
}

结果:

Base有参构造函数
Sub1含参构造函数
Base有参构造函数
Sub2含参构造函数
Child含参构造函数
val = 3
val = 3
Press any key to continue . . .

C++ 虚基类 派生与继承的更多相关文章

  1. C++ (P160—)多继承 二义性 虚基类 “向上转型”

    1 多继承中,必须给每个基类指定一种派生类型,如果缺省,相应的基类则取私有派生类型,而不是和前一个基类取相同的派生类型 2 一个类的保护成员只能被本类的成员函数或者它的派生类成员函数访问 3 由于c+ ...

  2. C++ 多继承与虚基类

    转载来自:CSDN insistGoGo  (http://blog.csdn.net/insistgogo) 多继承的定义:派生类的基类大于一个 语法: class  派生类名:继承方式1 基类名1 ...

  3. C++中虚基类在派生类中的内存布局

    今天重温C++的知识,当看到虚基类这点的时候,那时候也没有太过追究,就是知道虚基类是消除了类继承之间的二义性问题而已,可是很是好奇,它是怎么消除的,内存布局是怎么分配的呢?于是就深入研究了一下,具体的 ...

  4. C++ 虚继承实现原理(虚基类表指针与虚基类表)

    虚继承和虚函数是完全无相关的两个概念. 虚继承是解决C++多重继承问题的一种手段,从不同途径继承来的同一基类,会在子类中存在多份拷贝.这将存在两个问题:其一,浪费存储空间:第二,存在二义性问题,通常可 ...

  5. C++:虚基类

    4.4.3 虚基类1.没什么要引入虚基类 如果一个类有多个直接基类,而这些直接基类又有一个共同的基类,则在最底层的派生类中会保留这个间接的共同基类数据成员的多分同名成员.在访问这些同名的成员时,必须在 ...

  6. C++学习之路—继承与派生(三):多重继承与虚基类

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 多重继承是指一个派生类有两个或多个基类.例如,有 ...

  7. 【C++】继承(虚基类)

    类的继承与派生 面向对象技术强调软件的可重用性,这种重用性通过继承机制来实现.而在类的继承过程中,被重用的原有类称为基类,新创建的类称为派生类.派生类定义语法格式如下: class <派生类名& ...

  8. C/C++ 多继承{虚基类,虚继承,构造顺序,析构顺序}

    C/C++:一个基类继承和多个基类继承的区别 1.对多个基类继承会出现类之间嵌套时出现的同名问题,如果同名变量或者函数出现不在同一层次,则底层派生隐藏外层比如继承基类的同名变量和函数,不会出现二义性, ...

  9. C#虚基类继承与接口的区别

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

随机推荐

  1. Maven项目合并

    当多个项目之间有关联.依赖jar包有重复时,可以考虑进行合并.举例,我一开始有一个test-pilling项目,pom文件如下: <project xmlns="http://mave ...

  2. jvm是怎样调用方法的

    jvm内部有五种调用方法的指令 invokeinterface 用以调用接口方法,在运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用.(Invoke interface method) ...

  3. laravel 中间件学习

    http://blog.csdn.net/kwinh/article/details/56285204 http://blog.csdn.net/fationyyk/article/details/5 ...

  4. zk 06之:ZooKeeper命令、命令行工具及简单操作

    常用命令ZooKeeper 支持某些特定的四字命令字母与其的交互.它们大多是查询命令,用来获取 ZooKeeper 服务的当前状态及相关信息.用户在客户端可以通过 telnet 或 nc 向 ZooK ...

  5. php爬虫神器cURL

    cURL 网页资源(编写网页爬虫) 接口资源 ftp服务器文件资源 其他资源 static public function curl($url, $data = array(), $timeout = ...

  6. MongoDB 学习笔记(一)—— 安装入门

    注:我的环境是win7 32位. 下载安装 http://www.mongodb.org/downloads 解压即可.这里我重命名“mongodb”,存放的目录为E:\mongodb. 新建数据文件 ...

  7. Centos7 超简单将Centos的yum源更换为国内的阿里云源

    1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载新的CentOS-Base ...

  8. OCX RegSvr32 error

    [Window Title]RegSvr32 [Content]The module "tt.ocx" failed to load. Make sure the binary i ...

  9. Super Jumping! Jumping! Jumping(最大递增子序列的和)

    Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. May ...

  10. <转>Linux环境进程间通信--信号灯(四)

    http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/ 一.信号灯概述 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机 ...