英特尔C ++编译器将对象中的vptr(指向虚函数表的指针)存储在哪里?
我相信MSVC将它放在对象的开头,最后是gcc。什么是icpc(英特尔C ++编译器)?
答案 0 :(得分:3)
您始终可以查看此类和派生类中的第一个地址所在的位置:
#include <stdio.h>
class foo
{
public:
virtual int do_foo()=0;
};
class bar : public foo
{
public:
int bar;
int do_foo() {printf ("%08x %08x\n", this, &bar);}
};
int main()
{
bar a_bar;
a_bar.do_foo();
}
在我的Linux机器上,结果是:
bfdbef3c bfdbef40
...这正是你所期望的:第一个指针加上虚函数指针的大小,是第二个指针的位置。
答案 1 :(得分:1)
对于英特尔C ++编译器,对于Linux,我发现它是对象的开头。
代码:
#include <cstdio>
class A
{
int a, b;
public:
A(int a1, int b1): a(a1), b(b1) {}
virtual void p(void) { printf("A\n"); }
};
class B: public A
{
public:
B(int a1, int b1): A(a1, b1) {}
void p(void){ printf("B\n"); }
};
int main(void)
{
A a(1, 2); int p=10; A a1(5, 6);
B b(3, 4); int q=11; B b2(7, 8);
a.p();
b.p();
int * x=(int*)&a;
printf("%d %d %d %d\n", x[0], x[1], x[2], x[3]);
x=(int*)&b;
printf("%d %d %d %d\n", x[0], x[1], x[2], x[3]);
}
答案 2 :(得分:0)
你在“功能开头”是什么意思?无论如何,Windows编译器将vptr放在对象的偏移量0处,而Unix编译器将其放在最后一个成员数据之后。英特尔为Windows和Unix生成编译器,我希望Win版本在开头放置vptr,在对象末尾放置* nix版本。
答案 3 :(得分:0)
对象中vtable指针的位置与操作系统无关。它只是编译器和其他工具的惯例。
答案 4 :(得分:0)
除了满足您的好奇心之外,您问题的真正答案不会非常有用,因为C ++标准没有定义这样的细节。因此,任何编译器供应商都可以根据需要实现这些功能。 这是C ++没有跨平台ABI(应用程序二进制接口)的原因之一。