虚拟表内存位置
Virtual tables memory location
给定以下代码:
namespace Example1 {
class Base1 {
public:
Base1() {}
virtual ~Base1() {}
protected:
float data_Base1;
};
class Base2 {
public:
Base2() {}
virtual ~Base2() {}
protected:
float data_Base2;
};
class Derived : public Base1, public Base2 {
public:
Derived() {}
virtual ~Derived() {}
protected:
float data_Derived;
};
class Derived2 : public Base1 {
public:
Derived2() {}
virtual ~Derived2() {}
protected:
float data_Derived2;
};
}
int main (void)
{
using namespace Example1;
Base2* pbase2 = new Derived;
Base1* b = new Base1();
Base1* b2 = new Base1();
Derived* d = new Derived;
Derived* d2= new Derived;
Derived2* dd = new Derived2;
}
在visual studio 2012的编译器中,似乎在多重继承下,派生类包含n-1个额外的虚拟表。而这正是派生类所发生的。
但它似乎也发生与Derived2(只继承从Base1类)
这是dd内存映射:
Example1::Base1
__vfptr
[0] 0x00c4127b
这是b内存映射:
__vfptr
[0] 0x00c411ae
可以看到,第一个虚表槽的地址是不同的。例如,B和b2有相同的虚表。
好了,现在是两个问题:
1)为什么它们不共享同一个Base1虚拟表?(派生对象)
2)为什么派生类有必要保存n-1个虚拟表?(N表示派生类继承的类的数目)
谢谢!
首先,Derived2
与Base1
是另一种类型,所以除了虚函数表,它还需要其他一些信息。其次,至少Derived2
的析构函数与Base1
的析构函数是另一个函数,所以即使表中只有虚函数,表项也有是不同的。我不确定MSVC如何在多态类型上实现RTTI,但必须有一些与虚拟函数不同的类型标识,例如启用dynamic_cast
s。所以第一个条目很可能是指向RTTI的指针。我现在没有MSVC,但你可以试试这个:
struct Base {
virtual void foo() {};
virtual void bar() {};
virtual ~Base();
};
struct Derived {
virtual void foo() {};
virtual ~Derived();
};
int main() {
Base* b1 = new Base;
Base* b2 = new Derived;
};
现在检查两个创建对象的__vfptr
的前四个或五个元素,我猜你会看到一个相同的条目-它是指向Base::bar
的指针。其他的(指向RTTI的指针,foo和析构函数)应该是不同的。
也许你可以看到指针指向内存中的不同区域,因为RTTI指针可能指向数据段,而虚函数指针指向代码段。
Update:不需要在虚表本身中有RTTI条目-可能有些编译器仅仅通过比较虚表的地址来实现RTTI
每个类都有自己的变量表。在这种情况下,每个类都有一个唯一的虚析构函数,因此它本身就意味着虚函数表需要是不同的。如果要构造一个没有任何不同虚函数的类,则编译器可能会决定"重用"相同的虚函数表。但不能保证。
如果一个类派生自多个类,则需要为每个具有任何类型虚函数的类提供一个虚函数表。这样,如果类被转换(通过使用指向基类的指针或dynamic_cast)为其中一个基类,则可以调用两个基类的虚函数。
还要注意:编译器如何处理变量表完全取决于编译器,并且不能保证它们如何工作的任何方面。
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 内存所有位置 wxWidgets
- 为什么字符串的 move() 会改变内存中底层数据的位置?
- 如何在不等待检索的情况下获取C++中的内存位置?
- 内存中类位置的成员是否取决于类成员在类定义中的位置?
- 向量的内存位置不连续
- 如何根据C++在同一内存位置重新初始化 C# 中的对象(还是自动完成)?
- 常量引用的内存位置
- C++强制变量到一个固定的内存位置
- 为什么未初始化的内存位置的值给出 -842150451 的值?
- 为什么存储在内存位置的值会发生变化?
- 在特定内存位置构造 c++ 对象
- 如果不初始化结构中的向量,它会自动为空还是具有随机内存位置的值?
- 如何识别内存泄漏的位置
- 内存位置出现Microsoft C++异常:std::out_of_range
- 函数,返回变量c++占用的内存位置的大小
- 在尝试使用CUDA分配内存时,我遇到了访问冲突写入位置错误
- delete如何知道对象在内存中的起始位置
- 无法在 Opencv 中显示图像导致内存位置
- 如何修复<程序名称>中的"<内存位置>未处理的异常。Visual Studio 2017 中的访问冲突写入位置<内存位置>"