EverSpring working shop

To pursue creative ideas based on nature.

统计

留言簿(1)

他山之石

阅读排行榜

评论排行榜

面试中碰到的一个C++陷阱

面试官先问了几个老掉牙的问题,虚函数是用来干嘛的,动态邦定是怎么回事,虚函数表怎么回事,心中暗喜。逐一化解。然后此人漫不经心的来了一句,虚函数指针有多大。因为差不多是面试的尾声了,前面大家相谈甚欢,颇有相见恨晚之势。谁知道一切都是幻觉。俺想也没有想,虚函数指针么,不就是32位那么大么。面试官笑而不答,俺也自以为是。
。。。。。
若干天后一个人发呆,突然想起这个问题,貌似某天洒家曾经在写code的时候碰到过非静态成员函数指针类型不能赋给普通函数指针,因为成员函数指针必须包含this指针来限定。一拍大腿,那这样的话,那天俺信誓旦旦的告诉面试官 虚函数指针不就是普通函数指针么,就是大错特错啦。虽然不明白细节,但是如果不那么心急回答,即使不明白大小的确切值,也应该稍作停顿,告诉他可能有所不同。悔之晚矣。虽然进入后续环节,但是这个瑕疵对自己是大大的不利阿,而这个不利本身是可以避免的。

posted on 2009-03-17 22:01 everspring79 阅读(3029) 评论(21)  编辑 收藏 引用 所属分类: Notes

评论

# re: 面试中碰到的一个C++陷阱 2009-03-17 23:18 xxxx

那我告诉你,你现在的想法依然是错的

“成员函数指针必须包含this指针”,试问指针如何包含指针

方便的话说一下你是在面试哪家牛企?  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 09:18 梦在天涯

哦,只要是指针在32位就是4个字节,就是32位,没有错!  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 09:21 梦在天涯

大家说是不是,至于对static和非staic的编译后时候要多传this,那是参数的问题,不是指针的问题!

你可以参考我的C++对象模型系列,那从虚函数表中获得虚函数指针那就是int*++,那就是32位!

  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 10:01 everspring79

@xxxx
哈哈,其实成员函数指针不是普通意义上的指针,是个结构,可能包含指针或者偏移信息,而且应不同的编译器而不同,你还是研究下再来说我的想法是错的。当然我文中的表述并不精确。
我想面试官当时的目的是想我能表达出虚函数指针与普通函数指针的不同,虚函数指针并非传统意义上的指针。  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 10:04 wocow3

X86平台上,成员函数跟普通_cdecl函数的区别在于成员函数将this指针放到ecx寄存器中传递,其他函数参数还是跟_cdecl一样压栈
32位平台上一切指针都是32位的,你这么回答也不错。  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 10:04 everspring79

@梦在天涯
你获得的那个是地址,而非完全意义上的虚函数指针。我当时也是这么想的,VPTR加上位移获得虚函数地址。但是面试官既然问虚函数指针有多大,完美的回答应该告诉他虚函数指针本身不同于普通指针,除了地址信息还有别的内容。  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 10:55 Alex-Lee

6.函数与虚函数
编译器为每个有虚函数的类都建立一个虚函数表(其大小不计算在类中),并为这个类安插一个指向虚函数表的指针,即每个有虚函数的类其大小至少为一个指针的大小4
class A{
public:
int a;
void Function();
};
class B{
public:
int a;
virtual void Function();
};
class C:public B{
public:
char b;
};
class D:public B{
public:
virtual void Function2();
};
class E{
public:
static void Function();
};
sizeof (A) = 4 (内含一个int,普通函数不占大小)
sizeof (B) = 8 (一个int ,一个虚函数表指针)
sizeof (C) =12 (一个int ,一个虚函数表指针,一个char ,再加上数据对齐)
sizeof (D) = 8 (一个int ,一个虚函数表指针,多个虚函数是放在一个表里的,所以虚函数表指针只要一个就行了)
sizeof (E) = 1 (static 函数不占大小,空类大小为1)


参考:http://hi.baidu.com/weiloujushi/blog/item/33f7f8b75d7a35f330add131.html

等会验证下  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 13:28 Kevin Lynx

大家应该明确下这里讨论的东西,【虚函数指针】,终究来说还是指针,32位机器上就是32位。我觉得博主在这里和大家讨论并没有针对指针这个概念。成员函数指针也是个指针,也是32位,但是其指针值不同一般指针。

面试官问你的问题如果类似于:xxxx指针有多大。。那很明显,要么是他表述问题的能力有问题,要么是其真的不懂这些东西。面试你的人不见得就比你牛。
  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 14:00 wocow3

成员函数指针到底是个什么东西?
貌似不同的编译器有不同的实现。网上介绍gcc的实现是个结构体(手头没gcc没验证)。
对vc而言,它就是一个指针,一个32位的地址。
但是它的值根据声明的 成员函数指针 是否指向 虚函数 而不同。
如果成员函数指针声明是一个普通成员函数的指针,那它的值就是一个普通成员函数的地址。
如果成员函数指针声明是一个虚函数,那它的值就有来头了。

首先,C++标准要求:虚成员函数指针也要表现多态性,这就要求调用虚成员函数指针必须“动态的选择函数”。但是,由于虚成员函数指针它就是就是一个值,也就说它的值必须是编译期决定的,这是一对矛盾。

MS用了一个方法解决这个矛盾,如果源码中出现一个虚函数指针被一个虚函数 赋值,那么 这组虚函数序列 会多生成类似
??_9@$BA@AE PROC NEAR ; `vcall', COMDAT
mov eax, DWORD PTR [ecx]
jmp DWORD PTR [eax]
的一段代码,由这段代码去完成运行时的多态
同时,虚成员函数指针的值也是编译期指定的,也就是这里的??_9@$BA@AE
而源代码中通过嘘成员函数指针的调用,实际上就是??_9@$BA@AE这段代码的调用。
  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 14:08 Kevin Lynx

@wocow3
我刚写了点测试代码,发现我们楼上的几位观点都有点小错误。
是的,成员函数指针比普通的指针复杂得多。例如:
class Test
{
public:
virtual void print() {}
};

printf( "%d\n", sizeof( &Test::print ) );

就以上代码,我在VS2005下得出的结果是4(如我们所说),但是在gcc下得出的却是8!而gcc对于一般的函数(C函数)指针却是4.

并且,
typedef void (Test::*mem_fn_ptr)();
mem_fn_ptr p = &Test::print;
printf( "%d\n", p );
的结果在不同的编译器上也不同,gcc得出的如我所想,是一个偏移值,而VC则始终给出一个真正的地址值。更为奇怪的是,在gcc下去掉virtual关键字,即让print为一个普通函数,那么其值也为一个真正的地址值。

看来,这个面试官考的也许正是这个。无论如何,一个成员函数指针不同于普通指针。
参考:http://www.codeproject.com/KB/cpp/FastDelegate.aspx  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 14:11 everspring79

@Kevin Lynx
没错,这正是面试官想要得到的信息。  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 14:19 wocow3

虚成员函数指针在VC下就是4字节,gcc是个结构体,不同的编译器厂商有不同的实现。
但VC用普通的指针就实现了虚成员函数指针,代价是会为用到的每组虚成员函数生成多余的代码。  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 15:25 陈梓瀚(vczh)

虚函数还是普通的指针,难道你是pfn(params)而不是pClass->*pfn(params)么?this就在这里了,是你调用的时候给他的。  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 16:40 yindf

如果编译器相关,就没有意思了。

但我想说的是成员函数,和普通函数的区别仅有一点,就是第一个参数默认是这个类的引用,理论完毕。

VC和GCC的实现是不一样的,其实GCC的实现更好一点。

看这个 http://www.diybl.com/course/3_program/c++/cppjs/2008109/149428.html  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 20:46 jimsmorong

还是不太明白 楼主开多个说明一下好吧  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-18 20:48 everspring79

最近比较忙,等我闲下来写个专门的小文章解释一下。  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-19 10:05 humanchao

回答32位,其实没有错...
我觉得很多人面试官的动机和心态有问题,面试是一个试图发现优点的过程,需要必要的引导和解释,而我们更多的发现的却是:不想办法把你考倒,好像证明自己很没有水平...  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-19 10:54 梦在天涯

看来以后对这样的问题要说明是VC还是GCC!  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-19 14:52 Alex-Lee

虽然博主没有说的非常的明白,但是这中讨论,让大家获益匪浅。还是不错哦。  回复  更多评论   

# re: 面试中碰到的一个C++陷阱[未登录] 2009-03-19 16:33

俺的blog上面有篇文章是说这个的.
这个标准没规定,大小是多少都有可能.
比如GCC下可能是8
BCB下是12都可以.  回复  更多评论   

# re: 面试中碰到的一个C++陷阱 2009-03-23 13:16 Herb

看看底层的汇编就知道了  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理