标签: vptr

什么时候为对象设置虚拟表指针(在C++中)?

我知道对于任何具有虚函数的类或者从具有虚函数的类派生的类,编译器会做两件事.首先,它为该类创建一个虚拟表,然后,它将虚拟指针(vptr)放在该对象的基础部分中.在运行时,此vptr被分配并在对象实例化时开始指向正确的vtable.

我的问题是,在实例化过程中,这个vptr的确切位置是什么?这个vptr的赋值是否发生在构造函数之前/之后的对象的构造函数中?

c++ constructor virtual-functions vtable vptr

8
推荐指数
2
解决办法
6494
查看次数

当派生类没有覆盖虚函数时,为什么需要vptr?

class base {
public:
    void virtual fn(int i) {
        cout << "base" << endl;
    }
};

class der : public base{
    public:
    void  fn(char i) {
        cout << "der" << endl;
    }
};

int main() {

    base* p = new der;
    char i = 5;
    p->fn(i);
    cout << sizeof(base);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这里定义的函数fn的签名与base类中fn()定义的函数的签名不同,der虽然函数名称相同.因此,der类中定义的base函数隐藏了类函数fn().所以der fn的类版本不能通过调用来p->fn(i)调用; 没事.

我的观点是,为什么sizeofbase或者der4如果没有用的VTABLE的指针 …

c++ overriding virtual-functions vptr

8
推荐指数
1
解决办法
2249
查看次数

输入trait以标识主要基类

如果我有一个类Base,至少有一个虚函数,并且一个Derived类从中单独继承,(uintptr_t)derived - (uintptr_t)static_cast<Base*>(derived)则保证(由Itanium ABI)为零,即使Derived不是标准布局.然而,在一般情况下,这不一定是真的(例如,多重继承).

是否有可能编写一个特征,可用于检测一个类是否是另一个类的主要基类?

来自Itanium ABI的有用部分:

http://refspecs.linux-foundation.org/cxxabi-1.83.html

主要基类

对于动态类,它与偏移0共享虚拟指针的唯一基类(如果有).它是第一个(以直接基类顺序排列)非虚拟动态基类(如果存在).

动态类

需要虚拟表指针的类(因为它或其基数具有一个或多个虚拟成员函数或虚拟基类).

c++ memory-layout type-traits vptr itanium-abi

8
推荐指数
1
解决办法
1837
查看次数

为什么即使不涉及虚拟功能,虚拟继承也需要vtable?

我读了一个问题:C ++虚拟类继承对象大小问题,并且想知道为什么虚拟继承会在类中导致附加的vtable指针。

我在这里找到了一篇文章:https : //en.wikipedia.org/wiki/Virtual_inheritance

告诉我们:

但是,通常只能在运行时知道此偏移量,...

我在这里不了解与运行时相关的内容。完整的类继承层次结构在编译时就已经知道。我了解虚函数和基指针的用法,但是虚继承没有这种东西。

有人可以解释为什么某些编译器(Clang / GCC)使用vtable实现虚拟继承以及在运行时如何使用它吗?

顺便说一句,我也看到了这个问题:在虚拟继承的情况下使用vtable,但是它仅指向与虚拟函数相关的答案,这不是我的问题。

c++ virtual-inheritance vtable memory-layout vptr

8
推荐指数
2
解决办法
170
查看次数

什么时候vptr(指向vtable)被初始化为多态类?

这不是关于"什么时候创建VTABLE?" .相反,什么时候应该初始化VPTR?它是在构造函数的开头/结尾还是在构造函数之前/之后?

A::A () : i(0), j(0)  -->> here ?
{
  -->> here ?
  //...
  -->> here ?
}
Run Code Online (Sandbox Code Playgroud)

c++ constructor overriding virtual-functions vptr

7
推荐指数
1
解决办法
4151
查看次数

实现vptr的替代方案?

这个问题不是关于C++语言本身(即不是关于标准),而是关于如何调用编译器来实现虚函数的替代方案.

实现虚函数的一般方案是使用指向指针表的指针.

class Base {
     private:
        int m;
     public:
        virtual metha();
};
Run Code Online (Sandbox Code Playgroud)

等价地说C会是这样的

struct Base {
    void (**vtable)();
    int m;
}
Run Code Online (Sandbox Code Playgroud)

第一个成员通常是指向虚拟函数列表等的指针(应用程序无法控制的内存中的一块区域).在大多数情况下,这会在考虑成员之前花费指针的大小等等.因此在大约4个字节的32位寻址方案中等等.如果在应用程序中创建了40k多态对象的列表,则大约为40k x在任何成员变量等之前4个字节= 160k字节.我也知道这恰好是C++编译中最快和最常见的实现.

我知道多重继承很复杂(尤其是虚拟类,即菱形结构等).

另一种方法是将第一个变量作为vptrs表的索引id(等效于C,如下所示)

struct Base {
    char    classid;     // the classid here is an index into an array of vtables
    int     m;
}
Run Code Online (Sandbox Code Playgroud)

如果应用程序中的类总数小于255(包括所有可能的模板实例化等),则char足以保存索引,从而减少应用程序中所有多态类的大小(我排除了对齐问题)等).

我的问题是,在GNU C++,LLVM或任何其他编译器中是否有任何切换来执行此操作?或减少多态对象的大小?

编辑:我了解指出的对齐问题.还有一点,如果这是64位系统(假设为64位vptr),每个多态对象成员的成本约为8字节,那么vptr的成本就是内存的50%.这主要涉及大量创建的小型多态,所以我想知道如果不是整个应用程序,这个方案是否至少可以用于特定的虚拟对象.

c++ compiler-construction micro-optimization compiler-optimization vptr

7
推荐指数
1
解决办法
782
查看次数

为什么 vptr 作为具有虚函数的类的内存中的第一个条目存储?

对于某些编译器,如果一个类具有虚函数,则可以使用其对象的第一个字节的地址来访问其 vptr。例如,

\n\n
class Base{\npublic:\n    virtual void f(){cout<<"f()"<<endl;};\n    virtual void g(){cout<<"g()"<<endl;};\n    virtual void h(){cout<<"h()"<<endl;};\n};\n\nint main()\n{   \n   Base b;\n\n   cout<<"Address of vtbl\xef\xbc\x9a"<<(int *)(&b)<<endl;\n\n   return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我知道它取决于不同的编译器行为。既然存在 vptr 被存储为第一个条目的情况,那么这样做有什么好处呢?这是否有助于提高性能,或者仅仅是因为使用 &b 更容易访问 vbtl?

\n

c++ compiler-construction performance memory-layout vptr

7
推荐指数
1
解决办法
3179
查看次数

非多态类型的Dynamic_cast

我可以理解为什么dynamic_cast在这种情况下有效:

#include <iostream>

struct A{
    virtual ~A() = default;
};

struct B {
    virtual ~B() = default;
};

struct C : A, B{};

void f(const A &a) {
    if(auto p = dynamic_cast<const B*>(&a))
        std::cout << "a is a B" << std::endl;
}

int main() {
    f(C{});

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是为什么如果你从B中删除多态,它仍然有效:

#include <iostream>

struct A{
    virtual ~A() = default;
};

struct B {
};

struct C : A, B{};

void f(const A &a) {
    if(auto p = dynamic_cast<const B*>(&a))
        std::cout << …
Run Code Online (Sandbox Code Playgroud)

c++ dynamic-cast multiple-inheritance vtable vptr

7
推荐指数
1
解决办法
196
查看次数

为什么我的C++对象丢失了它的VPTr

在调试程序的核心转储之一时,我遇到了多态的包含对象失去其VPTr的情况,我可以看到它指向NULL.

当一个对象丢失其VPTr时可能出现的情况.

先谢谢,Brijesh

c++ linux vptr

6
推荐指数
2
解决办法
2730
查看次数

虚拟表和_vptr存储方案

有人可以解释这个不同类的虚拟表是如何存储在内存中的吗?当我们使用指针调用函数时,他们如何使用地址位置调用函数?我们可以使用类指针获取这些虚拟表内存分配大小吗?我想看看一个类的虚拟表使用了多少内存块.我怎么能看到它?

class Base
{
public:
    FunctionPointer *__vptr;
    virtual void function1() {};
    virtual void function2() {};
};

class D1: public Base
{
public:
    virtual void function1() {};
};

class D2: public Base
{
public:
    virtual void function2() {};
};
int main()
{
    D1 d1;
    Base *dPtr = &d1;
    dPtr->function1();
}
Run Code Online (Sandbox Code Playgroud)

谢谢!提前

c++ vtable vptr virtual-table

6
推荐指数
1
解决办法
897
查看次数