如果对象具有多态性而不是多重继承,则虚拟指针在对象中的位置是否不同?

凯特·德米特(Cail Demetri)

我正在尝试了解对象内的虚拟指针放置,请澄清一下。我研究了两个不同的场景,即多态和多重继承。两者对于虚拟指针的位置都有不同的答案。


多态性
虚拟指针位于对象的顶部,并且仅用于该类,这意味着只有一个虚拟指针。例如:

class A {
    public:
        virtual void walk();
}

class B : A {
    public:
        int num;

        virtual void walk();
        virtual void run();
}

内存中的对象将如下所示:

| vPointer to class B vTable |
| int num                    |



多重继承
有多个虚拟指针,每个类一个。但是,此类的vTable已更改,因此覆盖的方法被定向到当前类的地址功能代码。但是,我认为这意味着每个类都可能具有多个不同的vTable。例如:

class A {
    public:
        virtual void walk();
}

class B {
    public: 
        char name;            

        virtual void run();
}

class C : A, B {
    public:
        int num;

        virtual void run();
        virtual void walk();
        virtual void swim();
}

内存中的对象将如下所示:

| vPointer to class A vTable |
| vPointer to class B vTable |
| char name                  |
| int num                    |

两者都正确吗?我四处搜寻,但只能找到关于多重继承的说明,而关于多态性却一无所获。

任何帮助将非常感激。

谢谢你。

克里斯多夫(Christophe)

该标准没有说明虚拟功能和多态性的实现(甚至没有提到vtables)。与派生类的内存布局无关,对象是内存区域并且包含基础子对象。

因此,我的回答不是关于C ++标准的一般说明,而只是关于实现通常如何行为的务实解释。

如果您对此类实现方面感兴趣,我强烈建议您这篇DDJ文章该文章还解释了更复杂的情况,例如虚拟继承。

单继承多态

实际上,通过使用指向虚拟表的对象指针(由类的所有对象共享)来实现多态,其中包含指向虚拟函数的指针。文章解释了很好的效果如何。

vtable指针存储在对象的开头,因为它是确保可以有效调用虚函数而不知道所指向对象的确切布局的最有效方法:

A a; B b;    // example assumes that class B inherits A publicly 
A *p = &b;   // pointer to a base object for showing polymorphism in action   
...
p->walk();   // at this stage, you don't know if p points to A or B.  
             // Bus as vtable pointer ist at the begin of the object, you don't have to care

因此,正如您所描述的那样。您始终可以通过查看由编译器生成的汇编代码来获得确认,以了解隐式构造函数如何将vtable加载到对象中。

具有多重继承的多态性

多重继承意味着您的派生对象C有两个子对象,一个用于A,一个用于B。每个子对象必须像其任何其他类型的对象一样管理其vtable。这意味着有两个vtable,每个vtable位于子对象的开头:

| vPointer to class A vTable |
| data for A object          |   => here it's empty
| vPointer to class B vTable |
| char name                  |   => here the data for the b object 
| int num                    | 

这是必需的,因为您可以具有以下代码:

C c; 
A *pa = &c; B *pb = &c;
pa->walk(); pb->run(); 

但是派生类C是它自己的类,并且还定义了一个虚函数:

C *pc = &c;
pc->walk(); pc->run(); pc->swim(); 

因此,这意味着D也有一个vtable。它存储在哪里?它必须在对象的开头。因此,C的vtable将是A的vtable的超集:

| vPointer to class C vTable |   => the first functions in the table are those of A, followed by all the virtual functions of C.  
| data for A object          |   => here it's empty
| vPointer to class B vTable |
| char name                  |   => here the data for the b object 
| int num                    | 

这是MSVC2013为vtable生成的汇编程序:

CONST   SEGMENT
??_7C@@6BB@@@ DD FLAT:??_R4C@@6BB@@@            ; C::`vftable' loaded at begin of B object
    DD  FLAT:?run@B@@UAEXXZ                       ; this is in fact the vtable for B
CONST   ENDS
CONST   SEGMENT
??_7C@@6BA@@@ DD FLAT:??_R4C@@6BA@@@            ; C::`vftable' loaded at begin of C object
    DD  FLAT:?walk@A@@UAEXXZ                      ;  that's the subset for A 
    DD  FLAT:?swim@C@@UAEXXZ                      ;  that's the superset for C specific gunctions
CONST   ENDS

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如果对象具有多态性而不是多重继承,则虚拟指针在对象中的位置是否不同?

来自分类Dev

虚拟继承和多态性:谷物库是否在混乱对象布局?

来自分类Dev

具有基于概念的多态性的多重继承 C++

来自分类Dev

C ++多态性中的访问冲突(指向错误位置的虚拟指针函数?)

来自分类Dev

数组中对象的C ++多态性

来自分类Dev

具有多态性的C ++复制指针的向量

来自分类Dev

条件对C ++中的多态对象有什么作用?(包含多态性)

来自分类Dev

具有不同模板类型的子类的多态性

来自分类Dev

多态性并在C ++中定义不同对象的列表

来自分类Dev

Matlab中的继承多态性

来自分类Dev

Java中的继承和多态性

来自分类Dev

继承中的 Java Upcasting 或多态性

来自分类Dev

泛型中的多态性-传递继承的对象时发生编译错误(无法隐式转换类型)

来自分类Dev

OCaml对象的多态性键入问题

来自分类Dev

多态性对象的字符串

来自分类Dev

如何使用继承/多态性将JSON字符串解析为C#对象?

来自分类Dev

仅子类具有虚拟方法时使用多态性的问题

来自分类Dev

仅子类具有虚拟方法时使用多态性的问题

来自分类Dev

成员字段中的多态性,当字段是对象的集合时,这些对象也是继承树的一部分

来自分类Dev

C ++ std容器-没有指针的多态性。是否有可能?

来自分类Dev

为什么要使用继承和多态性而不是函数模板实例来调用具有相同签名的成员函数?

来自分类Dev

封装,抽象和多态性是否需要继承?

来自分类Dev

具有虚拟功能的C ++中的多重继承

来自分类Dev

C ++多态性-调用具有不同签名的派生类方法

来自分类Dev

Avro模式中的多态性和继承

来自分类Dev

在对象中具有类

来自分类Dev

F#是否具有行多态性(或类似的东西?)

来自分类Dev

F#是否具有行多态性(或类似的东西?)

来自分类Dev

是否具有虚拟成员的对象类?

Related 相关文章

  1. 1

    如果对象具有多态性而不是多重继承,则虚拟指针在对象中的位置是否不同?

  2. 2

    虚拟继承和多态性:谷物库是否在混乱对象布局?

  3. 3

    具有基于概念的多态性的多重继承 C++

  4. 4

    C ++多态性中的访问冲突(指向错误位置的虚拟指针函数?)

  5. 5

    数组中对象的C ++多态性

  6. 6

    具有多态性的C ++复制指针的向量

  7. 7

    条件对C ++中的多态对象有什么作用?(包含多态性)

  8. 8

    具有不同模板类型的子类的多态性

  9. 9

    多态性并在C ++中定义不同对象的列表

  10. 10

    Matlab中的继承多态性

  11. 11

    Java中的继承和多态性

  12. 12

    继承中的 Java Upcasting 或多态性

  13. 13

    泛型中的多态性-传递继承的对象时发生编译错误(无法隐式转换类型)

  14. 14

    OCaml对象的多态性键入问题

  15. 15

    多态性对象的字符串

  16. 16

    如何使用继承/多态性将JSON字符串解析为C#对象?

  17. 17

    仅子类具有虚拟方法时使用多态性的问题

  18. 18

    仅子类具有虚拟方法时使用多态性的问题

  19. 19

    成员字段中的多态性,当字段是对象的集合时,这些对象也是继承树的一部分

  20. 20

    C ++ std容器-没有指针的多态性。是否有可能?

  21. 21

    为什么要使用继承和多态性而不是函数模板实例来调用具有相同签名的成员函数?

  22. 22

    封装,抽象和多态性是否需要继承?

  23. 23

    具有虚拟功能的C ++中的多重继承

  24. 24

    C ++多态性-调用具有不同签名的派生类方法

  25. 25

    Avro模式中的多态性和继承

  26. 26

    在对象中具有类

  27. 27

    F#是否具有行多态性(或类似的东西?)

  28. 28

    F#是否具有行多态性(或类似的东西?)

  29. 29

    是否具有虚拟成员的对象类?

热门标签

归档