- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我试图使本书有效的c++中的语句有意义。以下是多重继承的继承图。
现在,这本书说vptr在每个类中都需要单独的内存。也有以下陈述
上图中的一个奇怪之处是,即使涉及四个类,也只有三个vptr。 如果愿意,实现可以自由生成四个vptr,但是三个就足够了(事实证明B和D可以共享一个vptr),并且大多数实现都利用此机会来减少编译器生成的开销。
我看不到任何理由为什么在vptr的每个类中都需要单独的内存。我了解vptr是从基类继承的,无论继承类型是什么。如果我们假设它显示了继承的vptr的结果内存结构,那么他们如何使该语句
B and D can share a vptr
最佳答案
您的问题很有趣,但是我担心您的首要目标是太大,因此,如果您不介意,我将分几个步骤进行回答:)
免责声明:我不是编译器作者,尽管我当然已经研究了该主题,但请谨慎使用。我会出现错误。而且我不太熟悉RTTI。而且,由于这不是标准的,所以我描述的是可能性。
1.如何实现继承?
注意:我将忽略对齐问题,它们只是意味着在块之间可以包含一些填充
现在,让我们省略虚拟方法,并集中在下面实现继承的方式。
事实是继承和构成有很多共同点:
struct B { int t; int u; };
struct C { B b; int v; int w; };
struct D: B { int v; int w; };
B:
+-----+-----+
| t | u |
+-----+-----+
C:
+-----+-----+-----+-----+
| B | v | w |
+-----+-----+-----+-----+
D:
+-----+-----+-----+-----+
| B | v | w |
+-----+-----+-----+-----+
struct A { int r; int s; };
struct M: A, B { int v; int w; };
M:
+-----+-----+-----+-----+-----+-----+
| A | B | v | w |
+-----+-----+-----+-----+-----+-----+
M* pm = new M();
A* pa = pm; // points to the A subpart of M
B* pb = pm; // points to the B subpart of M
M:
+-----+-----+-----+-----+-----+-----+
| A | B | v | w |
+-----+-----+-----+-----+-----+-----+
^ ^
pm pb
pa
pb
的地址与
pm
的地址略有不同的事实是由编译器自动通过指针算术处理的。
V
(用于虚拟)对象。让我们定义一个简单的菱形继承(钻石问题)。
struct V { int t; };
struct B: virtual V { int u; };
struct C: virtual V { int v; };
struct D: B, C { int w; };
D
对象中的
B
和
C
子部分共享同一子对象。如何做呢 ?
B
和
C
仅为
V
的指针保留空间,并且:
B
,则构造函数将在堆上分配一个V
,它将自动处理B
构建为D
的一部分,则B
子部分将期望D
构造函数将指针传递至V
的位置C
的思想。
D
中,优化使构造函数可以在对象中为
V
保留空间,因为
D
不会实际上从
B
或
C
继承,给出您所显示的图(尽管我们还没有虚拟方法)。
B: (and C is similar)
+-----+-----+
| V* | u |
+-----+-----+
D:
+-----+-----+-----+-----+-----+-----+
| B | C | w | A |
+-----+-----+-----+-----+-----+-----+
B
转换为
A
的过程比简单指针算法要复杂一些:您需要遵循
B
中的指针,而不是简单指针算法。
A
的指针,你怎么知道如何回到
B
?
dynamic_cast
执行的,但这需要存储在某处的某些支持(即信息)。这就是所谓的
RTTI
(运行时类型信息)。
dynamic_cast
将首先通过某种魔术来确定
A
是
D
的一部分,然后查询D的运行时信息以知道
D
子对象存储在
B
中的何处。
B
子对象,它将返回0(指针形式)或引发
bad_cast
异常(引用形式)。
struct B { virtual foo(); };
struct B { VTable* vptr; };
void Bfoo(B* b);
struct BVTable { RTTI* rtti; void (*foo)(B*); };
B
派生时:
struct D: B { virtual foo(); virtual bar(); };
B::foo
,另一种是全新的。计算机表示类似于:
struct D { VTable* vptr; }; // single table, even for two methods
void Dfoo(D* d); void Dbar(D* d);
struct DVTable { RTTI* rtti; void (*foo)(D*); void (*foo)(B*); };
BVTable
和
DVTable
有何相似之处(因为我们将
foo
放在
bar
之前)?这一点很重要!
D* d = /**/;
B* b = d; // noop, no needfor arithmetic
b->foo();
foo
:
// 1. get the vptr
void* vptr = b; // noop, it's stored at the first byte of B
// 2. get the pointer to foo function
void (*foo)(B*) = vptr[1]; // 0 is for RTTI
// 3. apply foo
(*foo)(b);
D
的构造函数时,会发生以下情况:
D::D()
首先调用B::B()
,以初始化其子部分B::B()
初始化vptr
指向其vtable,然后返回D::D()
初始化vptr
指向其vtable,覆盖B的vptr
指向D的vtable,因此应用的
foo
是D的。对于
B
,它是完全透明的。
关于c++ - 了解多继承的vptr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5684574/
我使用的是 PHP 5.3 稳定版,有时会遇到非常不一致的行为。据我所知,在继承中,父类(super class)中的所有属性和方法(私有(private)、公共(public)和 protected
所以我一直在努力寻找正确的方法来让应该非常简单的继承发挥作用(以我想要的方式 ;)),但我失败得很惨。考虑一下: class Parent { public String name = "Pare
给定这些类: class Father { public Father getMe() { return this; } } class Child extends Father {
为什么最后打印“I'm a Child Class”。 ? public class Parent { String parentString; public Parent()
我知道有很多类似的问题对此有很多很好的答案。我试着看看经典的继承方法,或者那些闭包方法等。不知何故,我认为它们对我来说或多或少是“hack”方法,因为它并不是 javascript 设计的真正目的。
我已经使用表单继承有一段时间了,但没有对以下方法进行太多研究。只需创建一个新类而不是表单并从现有表单继承并根据需要将所需控件转换为 protected 。 Visual Studio 2010 设计器
我原以为下面的代码片段会产生编译错误,因为派生类不会有我试图在 pub_fun() 中访问的 priv_var。但是它编译了,我得到了下面提到的输出。有人可以解释这背后的理论吗? class base
继承的替代方案有哪些? 最佳答案 Effective Java:优先考虑组合而不是继承。 (这实际上也来自《四人帮》)。 他提出的情况是,如果扩展类没有明确设计为继承,继承可能会导致许多不恰当的副作用
我有2个类别:动物( parent )和狗(动物的“ child ”),当我创建一个 Animal 对象并尝试提醒该动物的名称时,我得到了 undefined ,而不是她的真名。为什么?(抱歉重复发帖
我试图做继承,但没想到this.array会像静态成员一样。我怎样才能让它成为“ protected /公开的”: function A() { this.array = []; } func
在创建在父类中使用的 lambda 时,我试图访问子类方法和字段。代码更容易解释: class Parent { List> processors; private void do
如果我有一个对象,我想从“ super 对象”“继承”方法以确保一致性。它们将是混合变量。 修订 ParentObj = function() { var self = this; t
class Base { int x=1; void show() { System.out.println(x); } } class Chi
目前我正在尝试几种不同的 Javascript 继承方法。我有以下代码: (“借用”自 http://www.kevlindev.com/tutorials/javascript/inheritanc
我在 .popin-foto 元素中打开一个 popin。当我尝试在同一元素中打开子类 popin 时,它不起作用。 代码 这是 parent function Popin(container, ti
我有以下两个类: class MyClass { friend ostream& operatorvalue +=1; return *this; } 现在
有没有办法完全忽略导入到 html 文件中的 header 中的 CSS 文件? 我希望一个页面拥有自己独立的 CSS,而不是从任何其他 CSS 源继承。 最佳答案 您可以在本地样式表中使用 !imp
Douglas Crockford似乎喜欢下面的继承方式: if (typeof Object.create !== 'function') { Object.create = functio
假设我有以下代码: interface ISomeInterface { void DoSomething(); void A(); void B(); } public
class LinkedList{ public: int data; LinkedList *next; }; class NewLinkedList: public Lin
我是一名优秀的程序员,十分优秀!