虚基类

C++ Virtual 完美诠释

半腔热情 提交于 2020-03-22 18:03:43
解答了我的一些疑问,觉得写的不错!!!转载一下。 virtual在英文中表示“虚”、“虚拟”的含义。c++中的关键字“virtual”主要用在两个方面:虚函数与虚基类。下面将分别从这两个方面对virtual进行介绍。 1.虚函数 虚函数源于c++中的类继承,是多态的一种。在c++中,一个基类的指针或者引用可以指向或者引用派生类的对象。同时,派生类可以重写基类中的成员函数。这里“重写”的要求是函数的特征标(包括参数的数目、类型和顺序)以及返回值都必须与基类中的函数一致。如下所示: 可以在基类中将被重写的成员函数设置为虚函数,其含义是:当通过基类的指针或者引用调用该成员函数时,将根据指针指向的对象类型确定调用的函数,而非指针的类型。如下,是未将test()函数设置为虚函数前的执行结果: 在将test()函数设置为virtual后,执行结果如下: 如此,便可以将基类与派生类的同名方法区分开,实现多态。 说明: 1.只需将基类中的成员函数声明为虚函数即可,派生类中重写的virtual函数自动成为虚函数; 2.基类中的析构函数必须为虚函数,否则会出现对象释放错误。以上例说明,如果不将基类的析构函数声明为virtual,那么在调用delete p2;语句时将调用基类的析构函数,而不是应当调用的派生类的析构函数,从而出现对象释放错误的问题。 3.虚函数的使用将导致类对象占用更大的内存空间

C++三大特性

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

C++多重继承二义性解决

邮差的信 提交于 2020-02-13 00:25:56
1. 什么是多重继承的二义性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A{ public : void f(); } class B{ public : void f(); void g(); } class C: public A, public B{ public : void g(); void h(); }; 如果声明:C c1,则c1.f();具有二义性,而c1.g();无二义性(同名覆盖)。 2. 解决办法一 -- 类名限定 调用时指名调用的是哪个类的函数,如 1 2 c1.A::f(); c1.B::f(); 3. 解决办法二 -- 同名覆盖 在C中声明一个同名函数,该函数根据需要内部调用A的f或者是B的f。如 1 2 3 4 5 6 7 8 class C: public A, public B{ public : void g(); void h(); void f(){ A::f(); } }; 4. 解决办法三 -- 虚基类(用于有共同基类的场合) virtual 修饰说明基类,如: 1 class B1: virtual public B 虚基类主要用来解决多继承时,可能对同一基类继承继承多次从而产生的二义性。为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝。注意

C++类的继承与派生

孤街浪徒 提交于 2020-01-29 15:06:18
  C++中,继承就是在一个已存在的类的基础上建立一个新的类。已存在的类称为基类,又称父类;新建立类称为派生类,又称为子类。   基类是对派生类的抽象,派生类是对基类的具体化。 (一)派生类的定义与构成 1)派生类的定义   class 派生类名:类派生列表{     成员列表   };   类派生列表指定了一个或多个基类,形式如下:   访问权限标号 基类名1,访问权限标号 基类名2,... 2)派生类的构成   派生类由两部分组成:第一部分是从基类继承得到的,另一部分是自己定义的新成员,这些成员仍然分为三种访问属性。   注意,友元关系是不能继承的:一方面,基类的友元对派生类成员没有特殊的访问权限;另一方面,如果基类被授予了友元关系,则只有基类有特殊访问权限,该基类的派生类不能访问授予友元关系的类。   实际编程中,设计一个派生类包括三个方面工作:   a)从基类接收成员。   除了构造函数与析构函数之外,派生类会把基类的全部成员继承过来。   b)调整基类成员的访问。   程序员可以对接收的成员指定访问策略。   c)在定义派生类时增加新的成员。另外还应该自己定义派生类的构造函数和析构函数,因为它们不能从基类继承过来。 (二)派生类成员的访问   不同的继承方式决定了基类成员在派生类中的访问属性 1)公有继承   基类的公有成员和保护成员在派生类中保持原有访问属性

C++内存布局之虚拟继承

北城以北 提交于 2020-01-29 08:55:50
虚拟继承 即派生类继承多次基类,但在派生类中只存在一份基类的拷贝。编译器实现虚拟继承的方式并不相同,下面我结合VS2010来探讨C++虚拟继承。声明一个虚基类CommonBase,两个从虚基类虚拟派生Base1和Base2,然后D,公有多继承自Base1和Base2,具体类定义如下: class CommonBase { public: virtual void commonBaseFunc() = 0; private: int commonBase_data; }; class Base1 : public virtual CommonBase { public: virtual void Base1_Fun1(){} virtual void Base1_Fun2(){} virtual void commonBaseFunc(){} private: int Base1_data; }; class Base2 : public virtual CommonBase { public: virtual void Base2_Fun1(){} virtual void Base2_Fun2(){} private: int Base2_data; }; class Derived : public Base1, public Base2 { public: virtual

C++ 虚拟继承

眉间皱痕 提交于 2020-01-22 21:31:14
http://blog.csdn.net/wangxingbao4227/article/details/6772579 C++中虚拟继承的概念 为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。 class 派生类名:virtual 继承方式 基类名 virtual是关键字,声明该基类为派生类的虚基类。 在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用。 声明了虚基类之后,虚基类在进一步派生过程中始终和派生类一起,维护同一个基类子对象的拷贝。 C++虚拟继承 ◇概念: C++使用虚拟继承(Virtual Inheritance),解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。 ◇解决问题: 解决了二义性问题,也节省了内存,避免了数据不一致的问题。 ◇同义词: 虚基类(把一个动词当成一个名词而已) 当在多条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例

c++虚拟继承

孤街醉人 提交于 2020-01-22 21:30:18
◇概念: C++使用虚拟继承(Virtual Inheritance),解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。 ◇解决问题: 解决了二义性问题,也节省了内存,避免了数据不一致的问题。 ◇同义词: 虚基类(把一个动词当成一个名词而已) 当在多条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类。 ◇语法: class 派生类: virtual 基类1,virtual 基类2,...,virtual 基类n { ...//派生类成员声明 }; ◇执行顺序: 首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造; 执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造; 执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造; 执行派生类自己的构造函数; 析构以与构造相反的顺序执行; ◇因果: 多重继承->二义性->虚拟继承解决 ◇二义性: 1 #include<iostream> 2 using namespace std; 3 4 class base 5 { 6 public: 7 base()

第十四章 C++中的代码重用

旧巷老猫 提交于 2020-01-22 21:29:55
C++提供了下面几种代码重用的手段: 1. 继承( 公有继承 (is-a)、 私有继承和保护继承 (has-a)); 2. 包含/层次化/组合 (has-a); 3. 多重继承 4. 类模板 继承了实现就是继承了数据成员,继承了接口就是继承了成员函数。 接口 ( 派生类对象可以使用基类的方法 ) 和实现 ( 派生类对象存储了基类的数据成员, 实现 即为可以对数据成员进行操作(通过成员函数) ) 使用公有继承时,类可以继承接口,可能还有实现(基类的纯虚函数提供接口,但不提供实现)。获得接口是is-a关系的组成部分。而使用组合,类可以获得实现,但不能获得接口。不获得接口是has-a关系的组成部分。 虽然has-a关系的继承没有继承基类的接口,但可以在派生类的成员函数内部使用基类名和作用域运算符来访问基类方法。 私有继承 使用私有继承,基类的私有成员、保护成员都将成为派生类的私有成员。这意味着,基类方法不会成为派生类对象公有接口的一部分,但可以在派生类的成员函数中使用它们。 ‘包含‘ 将对象作为一个命名的成员对象添加到类中;而私有继承将对象作为一个未被命名的继承对象添加到类中。 私有继承的技术: 1. 初始化基类组件 构造函数使用成员初始化列表,使用类名而不是成员名来表示构造函数。 每一个继承的基类只对应一个成员对象。 2. 访问基类的方法 可以通过类名和作用域解析运算符来调用基类的方法

C++之继承与派生(3)

橙三吉。 提交于 2020-01-10 13:57:27
  大家都知道C#和C++重要的区别之一就是,C#支持单一继承和多接口继承,而C++则允许多继承。至于哪一个比较好,在这里就不去评价了。今天所要说的重点内容就是C++的多重继承以及虚基类。   1.前一节我介绍了有关单继承的内容,实际上,一个派生类可能会继承于两个或多了基类,那么这样的派生方法称为多基派生或多重继承。它声明的一般格式:   class 派生类名:继承方式1 基类名1, 继承方式2 基类名2, 继承方式3 基类名3, ...,继承方式n 基类名n   {     派生类新增的数据成员和成员函数;   } 在多重继承中,公有继承、保护继承以及私有继承对于基类成员在派生类中的访问属性与单继承的规则是相同的。同样的多重继承派生类的构造函数和析构函数又是如何定义呢?一般形式:   派生类名(参数总表):基类名1(参数子表1), 基类名2(参数子表2),...,基类名n(参数子表n)   {     派生类新增成员的初始化语句;   } 与单继承派生类构造函数一样,多继承下的派生类构造函数必须同时负责该派生类的所有基类构造函数的参数传递。且构造函数和析构函数的调用顺序和单继承是一样的(可参考 C++之继承与派生(2) ),先调用基类构造函数,再调用对象成员的构造函数,最后调用派生类的构造函数。那么处于同一层次的各个基类构造函数的调用顺序是取决于声明派生类时所指定的各个基类的顺序

C/C++ 复习

末鹿安然 提交于 2020-01-05 04:23:10
本文总结一下C++面试时常遇到的问题。C++面试中,主要涉及的考点有 关键字极其用法,常考的关键字有const, sizeof, typedef, inline, static, extern, new, delete等等 语法问题 类型转换 指针以及指针和引用的区别 面向对象的相关问题,如虚函数机制等 泛型编程的相关问题,如模板和函数的区别等 内存管理,如字节对齐(内存对齐)、动态内存管理、内存泄漏等 编译和链接 实现函数和类 本文不涉及STL的内容,有关STL的内容,会另有一篇文章专门总结。 零、序章 0.1 C++与C的对比 C++有三种编程方式:过程性,面向对象,泛型编程。 C++函数符号由 函数名+参数类型 组成,C只有函数名。所以,C没有函数重载的概念。 C++ 在 C的基础上增加了封装、继承、多态的概念 C++增加了泛型编程 C++增加了异常处理,C没有异常处理 C++增加了bool型 C++允许无名的函数形参(如果这个形参没有被用到的话) C允许main函数调用自己 C++支持默认参数,C不支持 C语言中,局部变量必须在函数开头定义,不允许类似for(int a = 0; ;;)这种定义方法。 C++增加了引用 C允许变长数组,C++不允许 C中函数原型可选,C++中在调用之前必须声明函数原型 C++增加了STL标准模板库来支持数据结构和算法 一