我对vptr和内存中对象的表示感到困惑,希望你能帮助我更好地理解这个问题.
考虑B从中继承A并定义虚函数f().从我了解到的记忆B类对象的表示是这样的:[ vptr | A | B ]
与vtbl该vptr指向包含B::f().我也明白,从铸造对象B来A什么都不做,除了忽略B在对象的端部.这是真的吗?这种行为不对吗?我们希望类型的对象A执行A::f()方法而不是B::f().
是否有一些vtables在系统中的类的数量?
一个将如何vtable类,由两个或多个类继承的是什么样子?如何将C的对象表示在内存中?
与问题3相同,但具有虚拟继承.
我正在调试一个缺陷,并将其缩小到对象的vtable指针0xdddddddd. 这个答案表明Win32调试版本通常会将死记忆或已删除的内存设置为此特殊值.
需要注意的是指针本身看起来有效,它只是虚函数表指针是0xdddddddd.
这是一段代码:
std::list<IMyObject*>::const_iterator it;
for (it = myObjects.begin(); it != myObjects.end(); ++it)
{
IMyObject* pMyObject = *it;
if (pMyObject == 0)
continue;
pMyObject->someMethod(); // Access violation
}
Run Code Online (Sandbox Code Playgroud)
如果我在访问冲突的行中断并观察pMyObject,我可以看到它pMyObject本身有一个有效的地址(0x08ede388)但该__vfptr成员是无效的(0xdddddddd).
一些说明:
有关如何进一步调试的任何建议?
我的一位朋友今天早些时候向我发出了以下挑战:
鉴于以下代码,建议执行
OBJECT_HAS_VTABLE程序打印AnObject has a vtable = 0, AnObjectWithVTable has a vtable = 1.
class AnObject
{
int m_a;
void DoSomething() {}
public:
AnObject() {m_a = 0;}
};
class AnObjectWithVTable
{
int m_b;
virtual void DoStuff() { }
public:
AnObjectWithVTable() {m_b = 0;}
};
void main()
{
printf("AnObject has a vtable = %i, AnObjectWithVTable has a vtable = %i\n",
OBJECT_HAS_VTABLE(AnObject),
OBJECT_HAS_VTABLE(AnObjectWithVTable));
}
Run Code Online (Sandbox Code Playgroud)
我想出了以下解决方案,我认为这个解决方案足够好了:
template <typename T>
bool objectHasVtable()
{
class __derived : public T {};
T t; …Run Code Online (Sandbox Code Playgroud) 以下面的代码片段为例:
struct Foo
{
typedef int type;
};
class Bar : private Foo
{
};
class Baz
{
};
Run Code Online (Sandbox Code Playgroud)
如您所见,此关系中不存在虚函数.既然如此,就语言而言,以下假设是否准确?
Bar.sizeof(Bar) == sizeof(Baz)基本上,我正在试图弄清楚我是否会为此付出任何代价.我的初始测试(虽然在单个编译器上)表明我的断言是有效的,但我不确定这是我的编译器的优化器还是对我所看到的负责的语言规范.
假设我们有以下程序:
class A
{ public:
virtual fun(){};
};
class B:public A
{ public:
virtual fun(){};
};
int main()
{
A a1;
B b1;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,当我们运行这个程序时,会创建多少vtables和多少vptrs?
可能重复:
了解vtable条目
使用g ++版本4.6.3,64位机器.我知道编译器可以随心所欲地实现虚函数.我想知道这里发生了什么.
我的课:
#include <iostream>
class test
{
public:
virtual void func(){std::cout<<"in class test";}
};
int main()
{
test obj;
obj.func();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
查看编译器生成的虚拟表,
Vtable for test
test::_ZTV4test: 3u entries
0 (int (*)(...))0 (<---- what is this? )
8 (int (*)(...))(& _ZTI4test)
16 (int (*)(...))test::func
Run Code Online (Sandbox Code Playgroud)
在偏移8处,它是RTTI
在偏移16处,它是虚函数的入口.
我的问题是为什么在偏移0处有空的条目,或者换句话说第一次进入的目的是什么?
PS我认为这可能与对齐有关,但后来我添加了更多的虚函数,但RTTI条目仍然是偏移8.
最近,我遇到了几个使用"手动"vtable的类型擦除实现 - Adobe ASLany_regular_t就是一个例子,虽然我已经看到它也用在Boost ASIO中(用于完成例程队列).
基本上,父类型传递一个指向静态类型的指针,该类型充满了在子类型中定义的函数指针,类似于下面的...
struct parent_t;
struct vtbl {
void (*invoke)(parent_t *, std::ostream &);
};
struct parent_t {
vtbl *vt;
parent_t(vtbl *v) : vt(v) { }
void invoke(std::ostream &os) {
vt->invoke(this, os);
}
};
template<typename T>
struct child_t : parent_t {
child_t(T val) : parent_t(&vt_), value_(val) { }
void invoke(std::ostream &os) {
// Actual implementation here
...
}
private:
static void invoke_impl(parent_t *p, std::ostream &os) {
static_cast<child_t *>(p)->invoke(os);
}
T value_;
static vtbl vt_;
};
template<typename …Run Code Online (Sandbox Code Playgroud) 据我所知,让班级sealed摆脱VTable中的查找或我错了吗?如果我创建一个类sealed,这是否意味着类层次结构中的所有虚方法也都标记了sealed?
例如:
public class A {
protected virtual void M() { ........ }
protected virtual void O() { ........ }
}
public sealed class B : A {
// I guess I can make this private for sealed class
private override void M() { ........ }
// Is this method automatically sealed? In the meaning that it doesn't have to look in VTable and can be called directly?
// Also what about O() can …Run Code Online (Sandbox Code Playgroud)