虚拟继承

Nov. 23. 2015

2015年11月23日

In this post, after introducing two preliminary concepts, I explain what virtual inheritance is, and how it is implemented, then introduce two applications of virtual inheritance. One involves multiple inheritance, and the other involves implementation of non-inheritability. For each case, one example demonstrating how virtual inheritance works is presented.

在本文中,在介绍了两个基本概念之后,我将解释什么是虚拟继承以及如何实现虚拟继承,然后介绍虚拟继承的两个应用程序。 一个涉及多重继承,另一个涉及非继承性的实现。 对于每种情况,都提供了一个示例说明虚拟继承如何工作。

一些初步 (Some Preliminaries)

Before discussing virtual inheritance, it is necessary to explain two very important concepts in OOP (Object Oriented Programming) concepts, static and dynamic binding.

在讨论虚拟继承之前,有必要解释OOP(O bjectØriented P在AGC)的概念, 动静结合两个非常重要的概念。

Roughly speaking, static binding occurs at compile time, and dynamic binding occurs at run time. In C++, the two kinds of polymorphism (see Appendix for Classification of Polymorphism), overloading and overriding are two typical examples of these two concepts. For function overloading, when an overloaded function is called, during compile time, the compiler determines which version is actually called by matching their parameter type patterns. Whereas, for function overriding, C++ implements virtual function call resolution with a vtable data structure [4]. In C++, virtual inheritance is also implemented with vtable. Next, we explain what virtual inheritance is, and how it is implemented.

粗略地说, 静态绑定发生在编译时,而动态绑定发生在运行时。 在C ++中,两种多态性(请参见附录中的多态性分类), 重载重载是这两个概念的两个典型示例。 对于函数重载,当调用重载函数时,在编译期间,编译器将通过匹配其参数类型模式来确定实际调用哪个版本。 而对于函数覆盖,C ++使用vtable数据结构实现虚拟函数调用解析[4]。 在C ++中,虚拟继承也可以通过vtable实现。 接下来,我们解释什么是虚拟继承,以及如何实现。

什么是“虚拟继承”? 我们为什么需要它? (What is “virtual inheritance”? why we need it?)

According to Wikipedia [1], “virtual inheritance is a technique used in C++, where a particular base class in an inheritance hierarchy is declared to share its member data instances with any other inclusions of that same base in further derived classes.

根据Wikipedia [1]的说法,“ 虚拟继承 是C ++中使用的一种技术,其中声明了继承层次结构中的特定基类,以与进一步派生类中相同基的任何其他包含物共享其成员数据实例。

It is well-known that, different from other OOP languages such as Java and C#, C++ supports multiple inheritance, which is complicated, and its necessity is controversial [2]. Virtual inheritance may be required when multiple inheritance is used. For example, diamond problem, which may cause name ambiguity, needs virtual inheritance to be solved when some member function(s) of the common base class is(are) not pure virtual. Next, we explain how virtual inheritance is implemented in C++.

众所周知,与Java和C#等其他OOP语言不同,C ++支持多重继承 ,这很复杂,其必要性引起争议[2]。 使用多重继承时,可能需要虚拟继承。 例如, 钻石类问题 (可能导致名称不明确)需要在公共基类的某些成员函数不是纯虚拟成员时解决虚拟继承问题。 接下来,我们解释如何在C ++中实现虚拟继承。

vtable —如何实现“虚拟继承”? (vtable — How “virtual inheritance” is implemented?)

Just similar to function overriding, C++ implement virtual inheritance with a vtable data structure. However, it is necessary to notice that different compilers may implement virtual inheritance with vtable in different ways.

与函数重写类似,C ++使用vtable数据结构实现虚拟继承。 但是,必须注意,不同的编译器可能以不同的方式使用vtable实现虚拟继承。

For g++ compiler, both virtual functions and virtual base classes share one single vtable. Every instance of a class with virtual inheritance begins with a virtual pointer to the corresponding class.

对于g ++编译器,虚拟函数和虚拟基类都共享一个单独的vtable。 具有虚拟继承的类的每个实例都以指向相应类的虚拟指针开始。

For MSVC compiler, virtual functions and virtual base classes are stored in separate vtables, and the table for virtual functions is named as vftbl, and the table for virtual base classes is called vbtbl.

对于MSVC编译器,虚拟函数和虚拟基类存储在单独的vtable中,虚拟函数的表名为vftbl,虚拟基类的表称为vbtbl。

“钻石问题”与虚拟继承 (“Diamond Problem” and Virtual Inheritance)

class Employee
{
public:
int e_id;
string e_name;
virtual int eSalary() const;
};class Manager: public Employee
{
public:
int eSalary() const;
};class Contractor: public Employee
{
public:
int eSalary() const;
};class TempManager: public Manager, public Contractor
{
public:
int eSalary() const;
};

附录:多态性分类 (Appendix: Classification of Polymorphism)

Following Cardelli and Wegner [3], Polymorphism can be classified into two categories and four different kinds:

根据Cardelli和Wegner [3], 多态性可以分为两类和四种不同的类型:

  • Ad-hoc Polymorphism (a.k.a non-universal polymorphism): ad-hoc polymorphic functions work on a finite set of different and potentially unrelated types. There are two kinds of ad-hoc polymorphism: overloading and coercion.

    临时多态性 (又名非通用多态性):临时多态性函数在一组有限的不同且可能不相关的类型上起作用。 有两种即席多态性:重载和强制。

  1. Overloading: the same name is used to denote different functions, and the context is used to decide which function is denoted by a particular instance of the name. In C++, overloading occurs in the same class, and at compile time (this is why it is called static binding or early binding).

    重载 :相同的名称用于表示不同的功能,上下文用于确定名称的特定实例表示哪个功能。 在C ++中,重载发生在同一类中,并且在编译时发生(这就是为什么将其称为静态绑定早期绑定 )。

  2. Coercion (a.k.a casting): a coercion is a semantic operation which is needed to convert an argument to the type expected by a function. Coercions can be provided statically, by automatically inserting them between arguments and functions at compile time, or may have to be determined dynamically by run-time tests on the arguments.

    强制 (aka 强制 转换 ):强制是一种语义运算,需要将参数转换为函数期望的类型。 强制可以通过在编译时自动在参数和函数之间插入强制来提供,也可以通过对参数进行运行时测试来动态确定。

  • Universal Polymorphism: universally polymorphic functions work on an infinite number of types with a given common structure. There are two kinds of universal polymorphism: parametric and subtyping.

    通用多态性 :通用多态函数可在具有给定通用结构的无数类型上工作。 通用多态性有两种:参数化和子类型化。

  1. Parametric: a polymorphic function has an implicit or explicit type parameter, which determines the type of the argument for each application of that function. This kind of polymorphism lets us to define codes that are generic: they can be instantiated to handle different types, and the functions that exhibit parametric polymorphism are also called generic functions. In C++, this kind of polymorphism is implemented with templates.

    参数 :多态函数具有隐式或显式类型参数,该参数确定该函数的每个应用程序的参数类型。 这种多态性使我们可以定义通用的代码:可以实例化它们以处理不同的类型,而表现出参数多态性的函数也称为通用函数 。 在C ++中,这种多态性是通过template实现的。

  2. Subtyping (a.k.a Inclusion Polymorphism, Dynamic Polymorphism or Runtime Polymorphism): an object can be viewed as belonging to many different classes which need not be disjoint, i.e. there may be inclusion of classes. In this polymorphism, elements of a subrange type also belong to superrange types, and this is the well-known Liskov’s Substitution Principle, which says that in any situation in which the left-hand-side of an assignment expects a type T, it can also receive a type S, as long as S is subtype of T. In C++, if we have a class D inherits from another class B, then any function accepting an argument of type B (either variable of type B, or reference or pointer to B) will also accept an argument of type D (variable of type D, or reference or pointer to D).

    子类型化 (又名“ 包含多态” ,“ 动态多态”或“ 运行时多态” ):可以将一个对象视为属于许多不同类别的对象,这些类别不必是不相交的,即可以包含类别。 在这种多态性中,子范围类型的元素也属于超范围类型,这就是众所周知的Liskov的“替换原理” ,它表示在任何情况下,如果赋值的左侧期望类型T,它都可以还接收一个S型,只要S是T.在C ++亚型,如果我们有从另一个类B中d类继承,那么任何函数接受B(B型的任一变量,或引用或指针的参数到B)也将接受型d(d,或引用或指针d)的可变的参数。

翻译自: https://medium.com/swlh/virtual-inheritance-d83f7873180e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值