虚继承

C++类的大小计算汇总

≯℡__Kan透↙ 提交于 2020-03-11 03:59:33
  C++中类涉及到虚函数成员、静态成员、虚继承、多继承、空类等。   类,作为一种类型定义,是没有大小可言的。   类的大小,指的是类的对象所占的大小。因此,用sizeof对一个类型名操作,得到的是具有该类型实体的大小。 类大小的计算,遵循结构体的对齐原则; 类的大小,与普通数据成员有关,与成员函数和静态成员无关。即普通成员函数、静态成员函数、静态数据成员、静态常量数据成员,均对类的大小无影响; 虚函数对类的大小有影响,是因为虚函数表指针带来的影响; 虚继承对类的大小有影响,是因为虚基表指针带来的影响; 静态数据成员之所以不计算在类的对象大小内,是因为类的静态数据成员被该类所有的对象所共享,并不属于具体哪个对象,静态数据成员定义在内存的全局区; 空类的大小( 类的大小为1 ),以及含有虚函数,虚继承,多继承是特殊情况; 计算涉及到内置类型的大小,以下所述结果是在64位gcc编译器下得到(int大小为4,指针大小为8); 一、简单情况的计算 #include<iostream> using namespace std; class base { public: base()=default; ~base()=default; private: static int a; int b; char c; }; int main() { base obj; cout<<sizeof

C++三大特性

青春壹個敷衍的年華 提交于 2020-03-10 23:58:03
封装继承和多态 封装:隐藏实现细节,使得代码模块化,封装就是把过程和数据包装,将客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操纵,对其他信息隐藏。 类继承是指C++提供来扩展和修改类的方法,类继承就是从已有的类中派生出新的类,派生类继承了基类的特性,同时可以添加自己的特性,继承又分为 单一继承 多重继承 菱形继承 多态是在具有继承关系的类对象中去调用某一虚函数时(使用基类的指针/引用去调用同一函数),产生了不同的行为,构成多态的条件有两个( 说白了就是通过指针/引用在不同时候调用同一函数可能调用的是不同的版本,多态是指接口的多种不同实现方式 ) 调用函数的对象必须是指针或者引用 被调用的函数必须是虚函数,且完成了虚函数的重写(不覆盖会调用派生类的函数吗?) 动态(类型)绑定/静态(类型)绑定 静态类型:对象在声明时的类型,其在编译时决定 动态类型:变量所指向内存中该对象的类型(通常指指针/引用所绑定对象的类型),在运行期决定 静态类型决定了某个函数能不能被调用,而动态类型则在动态绑定发生时决定调用该函数的哪个版本 如果不使用指针和引用,则静态类型和动态类型一定相同 静态绑定:也叫静态联编,绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译器 动态绑定:也叫动态联编,绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型

多继承与虚继承

你说的曾经没有我的故事 提交于 2020-03-01 03:08:10
多继承 派生类有多个基类继承而来叫做多继承,其构造时按照基类在派生类中的声明顺序依次进行,由于派生类有多个基类派生而来,所以可能出现命名冲突,出现冲突时使用::指明到底使用的是哪个类的成员。 c由AB派生而来,其内存模型如上图所示。 虚继承(菱形继承) 菱形继承: 类 A 派生出类 B 和类 C,类 D 继承自类 B 和类 C,这个时候类 A 中的成员变量和成员函数继承到类 D 中变成了两份,一份来自 A–>B–>D 这条路径,另一份来自 A–>C–>D 这条路径。当需要访问A的成员变量时,就会产二义性。 解决方法: 采用虚继承在继承方式前面加上 virtual ,派生类中只保留一份间接类的成员。 虚继承的类也叫做虚基类 虚继承时的构造函数 以上为例D的析构函数,不仅要调用BC的构造函数还有直接调用A的构造函数 虚继承时构造函数的执行顺序与普通继承时不同:在最终派生类的构造函数调用列表中,不管各个构造函数出现的顺序如何,编译器总是 先调用虚基类的构造函数 ,再按照出现的顺序调用其他的构造函数;而对于普通继承,就是按照构造函数出现的顺序依次调用的。 来源: CSDN 作者: 和平精英总指挥 链接: https://blog.csdn.net/weixin_44997886/article/details/104581481

C++对象模型:单继承,多继承,虚继承

泄露秘密 提交于 2019-12-24 14:13:08
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 什么是对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分。 对于各种支持的底层实现机制。 类中成员分类 数据成员分为静态和非静态,成员函数有静态非静态以及虚函数 class data members:static和nonstatic class data functions:static、nonstatic和virtual 比如: class Base { public: Base(int i) :baseI(i){}; int getI(){ return baseI; } static void countI(){}; virtual void print(void){ cout << "Base::print()"; } virtual ~Base(){} private: int baseI; static int baseS; }; 对象模型分类 简单对象模型 :这个模型非常地简单粗暴。在该模型下,对象由一系列的指针组成,每一个指针都指向一个数据成员或成员函数,也即是说,每个数据成员和成员函数在类中所占的大小是相同的,都为一个指针的大小。这样有个好处——很容易算出对象的大小,不过赔上的是空间和执行期效率。所以这种对象模型并没有被用于实际产品上。 表格驱动对象模型

重拾C++之虚函数和虚基类以及抽象类

霸气de小男生 提交于 2019-12-24 14:09:47
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 一、引言 好久没接触过C++了,今天突然要用一点感觉号蛋疼,用惯了python感觉C++一点都不会了。 声明了一个类的对象居然用这种方法,脑子绝对是被驴(python)踢了 class A{ ... } a=A();//尼玛这都能行,被踢大了 二、虚函数和一般函数 虚函数就是加了vritual关键字的函数,引入虚函数的目的是为了实现多态性(在此为运行时的多态性),即可以通过父类的指针调用子类的对象,从而产生不同的效果。 virtual void show(){ cout<<"hello my name is a"<<endl; } 废话不多说,为了展示虚函数和一般函数的区别看看下面一个个例子: #include<iostream> using namespace std; class A{ private: int a; int b; public: A(int a,int b){ this->a=a; this->b=b; cout<<"hello base A"<<endl; cout<<a<<'-'<<b<<endl; } //定义一个虚函数 virtual void show(){ cout<<"hello my name is a"<<endl; } }; class D:public A{

c++设计一个不能被继承的类,为什么必须是虚继承?原因分析

房东的猫 提交于 2019-12-10 17:55:13
用C++实现一个不能被继承的类(例1) #include <iostream> using namespace std; template <typename T> class Base{ friend T; private: Base(){ cout << "base" << endl; } ~Base(){} }; class B:virtual public Base<B>{ //一定注意 必须是虚继承 public: B(){ cout << "B" << endl; } }; class C:public B{ public: C(){} //继承时报错,无法通过编译 }; int main(){ B b; //B类无法被继承 //C c; return 0; } 类Base的构造函数和析构函数因为是私有的,只有Base类的友元可以访问,B类在继承时将模板的参数设置为了B类,所以构造B类对象时们可以直接访问父类(Base)的构造函数。 为什么必须是虚继承(virtual)呢? 参见 c++Primer 4th 第17.3.7节 特殊的初始化语义 通常每个类只初始化自己的直接基类,但是在虚继承的时候这个情况发生了变化,可能导致虚基类被多次初始化,这显然不是我们想要的。(例2: AA,AB都是类A的派生类,然后类C又继承自AA和AB,如果按之前的方法会导致C里面A被初始化两次

第53课.被遗弃的多重继承(上)

帅比萌擦擦* 提交于 2019-12-06 14:30:40
1.c++中的多重继承 a.c++支持编写多重继承的代码 b.一个子类可以拥有多个父类 c.子类拥有父类的成员变量 d.子类继承所有父类的成员函数 e.子类对象可以当做任意杜磊对象使用(退化) 语法规则: class Derived : public BaseA, public BaseB, public BaseC { // 多重继承的本质与单继承相同 } 2.多重继承的问题一 多重继承时得到的对象可能拥有不同的地址。 #include <iostream> #include <string> using namespace std; class BaseA { int ma; public: BaseA (int a) { ma = a; } int getA () { return ma; } }; class BaseB { int mb; public: BaseB (int b) { mb = b; } int getB () { return mb; } }; class Derived : public BaseA, public BaseB { int mc; public: Derived (int a, int b, int c) : BaseA(a), BaseB(b) { mc = c; } int getC () { return mc; } void

C++ 虚继承

假如想象 提交于 2019-12-04 16:27:08
如果不虚继承的话,父类对象每一次被调用都会被初始化 #include <iostream> /** * C++多重继承 */ using namespace std; class Person { public: Person(string color="blue"); virtual ~Person(); void printColor(); protected: string m_strColor; }; //虚继承 class Farmer :virtual public Person{ public: Farmer(string name = "jack",string color="blue"); ~Farmer(); void sow(); protected: string m_strName; }; //虚继承 class Worker :virtual public Person{ public: Worker(string code = "001",string color="bule"); virtual ~Worker(); void carry(); protected: string m_strCode; }; void Worker::carry() { cout << m_strCode << endl; cout << "Worker::carry

C++ 对象的内存布局

匿名 (未验证) 提交于 2019-12-03 00:18:01
http://www.jb51.net/article/101126.htm c++中一个类中无非有四种成员:静态数据成员和非静态数据成员,静态函数和非静态函数。 1、 非静态数据成员被放在每一个对象体内作为对象专有的数据成员。 2、 静态数据成员被提取出来放在程序的静态数据区内,为该类所有对象共享,因此只存在一份。 3、 静态和非静态成员函数最终都被提取出来放在程序的代码段中并为该类所有对象共享,因此每一个成员函数也只能存在一份代码实体。在c++中类的成员函数都是保存在静态存储区中的 ,那静态函数也是保存在静态存储区中的,他们都是在类中保存同一个惫份。 因此, 构成对象本身的只有数据 ,任何成员函数都不隶属于任何一个对象,非静态成员函数与对象的关系就是绑定,绑定的中介就是this指针。成员函数为该类所有对象共享,不仅是处于简化语言实现、节省存储的目的,而且是为了使同类对象有一致的行为。同类对象的行为虽然一致,但是操作不同的数据成员。 #include"iostream.h" class A { private : int x; int y; public : void sety() { y=5; } void print() { cout<< "x=" <<x<<endl<< "y=" <<y<<endl; } }; void main() { A a; a.sety(); a

c++第四次作业

人盡茶涼 提交于 2019-12-01 07:23:16
C++类的继承 1:类的继承 2:共性与个性 3:共性表示为父类(基类),个性表示为子类(派生类) 4:继承的语法 5:继承表 6:继承方式 7:继承的基本特点 公共特点 1:向上和向下转换(造型) 2:子类会继承父类的所有成员(公开、私有和保护) 3:子类会隐藏父类的同名成员 4:继承方式影响访问控制 5:访问控制限定符 继承方式的影响范围 1:私有继承、保护继承 2:多重继承、钻石继承、虚继承 3:多重继承 4:名字冲突 5:钻石继承 6:虚继承 virtual 7:构造函数 8:拷贝构造 类的继承 共性与个性 共性表达不同类型事物之间工友的属性和行为。 个性用于刻画每种事物特有的属性和行为。 共性表示为父类(基类),个性表示为子类(派生类) 子类继承自父类 基类派生出子类 继承的语法 继承表 一个子类可以同时继承0~多个父类,每个父类的继承方式可以相同也可以不相同。 class 子类:继承方式1 父类1,继承方式2 父类2,... { } 继承方式 public 公有继承:父类的特性可以通过子类向外扩展。 private 私有继承:父类的特性只能为子类所有。 protected 保护继承:父类的特性只能在继承链内扩展。 继承的基本特点 公共特点 1、子类对象可以当作父类对象使用,子类对象与父类对象没有本质上的区别。 2、子类的逻辑空间小于父类,但它的物理空间要大于等于父类。