C++ 虚基类 派生与继承
在学习设计模式时我就有一个疑问,关联和继承除了用法上的区别,好像在内存上并没有什么区别,继承也是父类作为了子类的元素(内存上),关联也是这样。而且关联好像更占内存一些。这就是设计模式里问题了“依赖倒转原则”。
继承分为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++ 虚基类 派生与继承的更多相关文章
- C++ (P160—)多继承 二义性 虚基类 “向上转型”
1 多继承中,必须给每个基类指定一种派生类型,如果缺省,相应的基类则取私有派生类型,而不是和前一个基类取相同的派生类型 2 一个类的保护成员只能被本类的成员函数或者它的派生类成员函数访问 3 由于c+ ...
- C++ 多继承与虚基类
转载来自:CSDN insistGoGo (http://blog.csdn.net/insistgogo) 多继承的定义:派生类的基类大于一个 语法: class 派生类名:继承方式1 基类名1 ...
- C++中虚基类在派生类中的内存布局
今天重温C++的知识,当看到虚基类这点的时候,那时候也没有太过追究,就是知道虚基类是消除了类继承之间的二义性问题而已,可是很是好奇,它是怎么消除的,内存布局是怎么分配的呢?于是就深入研究了一下,具体的 ...
- C++ 虚继承实现原理(虚基类表指针与虚基类表)
虚继承和虚函数是完全无相关的两个概念. 虚继承是解决C++多重继承问题的一种手段,从不同途径继承来的同一基类,会在子类中存在多份拷贝.这将存在两个问题:其一,浪费存储空间:第二,存在二义性问题,通常可 ...
- C++:虚基类
4.4.3 虚基类1.没什么要引入虚基类 如果一个类有多个直接基类,而这些直接基类又有一个共同的基类,则在最底层的派生类中会保留这个间接的共同基类数据成员的多分同名成员.在访问这些同名的成员时,必须在 ...
- C++学习之路—继承与派生(三):多重继承与虚基类
(根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 多重继承是指一个派生类有两个或多个基类.例如,有 ...
- 【C++】继承(虚基类)
类的继承与派生 面向对象技术强调软件的可重用性,这种重用性通过继承机制来实现.而在类的继承过程中,被重用的原有类称为基类,新创建的类称为派生类.派生类定义语法格式如下: class <派生类名& ...
- C/C++ 多继承{虚基类,虚继承,构造顺序,析构顺序}
C/C++:一个基类继承和多个基类继承的区别 1.对多个基类继承会出现类之间嵌套时出现的同名问题,如果同名变量或者函数出现不在同一层次,则底层派生隐藏外层比如继承基类的同名变量和函数,不会出现二义性, ...
- C#虚基类继承与接口的区别
类:定义新的数据类型以及这些新的数据类型进行相互操作的方法 定义方式: class Cat { } class Cat:object { } C#中所有的类都是默认由object类派生来的,显示指定或 ...
随机推荐
- unidac 执行Execute后取得受影响行数。
unidac 执行Execute后取得受影响行数. uniQuery2.SQL.Text := mmo2.Text; uniQuery2.Execute; mmo1.Lines.Add(Format( ...
- GOF23设计模式之工厂模式(factory)
一.工厂模式概述 实现了创建者和调用者的分离 (1)分类 ①简单工厂模式 虽然某种程度不符合设计原则,但实际使用最多. ②工厂方法模式 不修改已有类的前提下,通过增加新的工厂类实现扩展. ③抽象工厂模 ...
- java图形用户界面添加图片的代码
package com.aa; import java.awt.Component; import javax.swing.ImageIcon; import javax.swing.JPanel; ...
- Mongodb时间问题
Java保存到mongodb当前时间,使用RoboMongo查看数据显示时间比当前时间少8个小时,这是客户端的问题. MongoDB中的Date类型数据只保存绝对时间值,不保存时区信息,因此“显示的时 ...
- AJAX验证此ID是否有对应的name
在表格输入一个ID,然后自动根据ID在数据库中查找是否有对应name 这是javascript部分,利用ajax验证 $(document).ready(function() { $("#c ...
- nginx 配置隐藏index.php效果
location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; } } 完整如下 server { li ...
- xunsearch使用SCWS
目录 创建分词对象 获取分词结果 提取重要词汇 在 Xunsearch 使用 SCWS 创建分词对象 $xs = new XS('my'); // 必须先创建一个 xs 实例,否则会抛出异常 $tok ...
- Zabbix 客户端自定义端口监控
http://www.linuxidc.com/Linux/2013-05/83780.htm
- js中的Math
js中的Math Math.round 取最接近的整数 Math.round(-2.7) // -3 Math.ceil 向上取整 Math.ceil(1.1) // 2 Math.floor 向下取 ...
- 第九章 整合Mybatis(待续)
··········