还有这样的虚函数面试题


两个类A和B,没有继承关系!!! 没有继承关系!!!
class A {
public:
void f1() {
printf("A::f1\n");
}
virtual void f2() {
printf("A::f2\n");
}
static  void f3() { printf("A::f3\n"); }
virtual void f4() { printf("A::f4\n"); }
};


class B {
public:
virtual void f1() {
printf("B::f1\n");
}
virtual void f2() {
printf("B::f2\n");
}
static void f3() { printf("B::f3\n"); }
virtual void f4() { printf("B::f4\n"); }
};


问以下输出什么?
int main()
{
B object;
A *p = (A *)&object;
p->f1();
p->f2();

return 0;
}

结果:
A::f1
B::f1

请大神来分析一下!~

#笔试题目##C++工程师#
全部评论
        首先创建一个类对象的话,这个对象内存空间里面只有类的非静态成员和虚指针vptr(指向虚函数表)。        然后说下编译器怎么调用非虚函数。非虚函数不在对象的内存空间中,所以编译器只能通过指向类的成员函数的指针(&A::*ptr,ptr是指向函数的指针,这个表达式应该是这么写的,如果我没记错的话。)来访问,而不是通过this指针(this指针是对象的地址)。        再说下编译器怎么调虚函数,虚函数地址存在虚函数表vtbl里,类的对象里又有个指向虚函数表的指针vptr。所以调用方式应该是先通过this指针找到虚表指针vptr,然后虚表指针通过下标访问到对应的虚函数地址。编译的时候编译器只知道你这个函数是虚函数,地址在虚函数表中是第几个位置,但是它不知道是子类的虚函数,还是派生类的,还是其他类的,要运行时才能确认。        你这里的A类的f1不是虚函数,所以在编译期就已经静态绑定了,编译器知道你调用的是a类的非虚函数。编译的时候编译器知道你创建了一个A类的指针,所以在编译时期你这个类的静态类型就是A类,然后会给你绑定f1函数。况且你不需要通过this指针来调非虚函数,所以这里调的是A::f1。        这里程序运行时期,A类指针指向了一个B类地址。调用虚函数的时候是(this->vptr)[虚函数在虚表中的位置索引],得到虚函数地址。刚说了虚函数怎么调的,编译的时候获得了索引1,因为f2是A类第一个虚函数,虚函数表第0位是(RTTI用于运行时类型确认)。然后你现在运行时,你调用的又是B的虚表,因为vptr改变指向了,原来指向A的虚表,现在指向B的了,但是B的第一个虚函数又是f1,所以它访问到的自然也就是B::f1。我暂时只能这么理解。。。
点赞 回复
分享
发布于 2019-08-24 01:18
虚表函数布局
点赞 回复
分享
发布于 2019-08-23 22:44
联易融
校招火热招聘中
官网直投
不应该是
点赞 回复
分享
发布于 2019-08-23 22:50
A::f1 B::f2吗
点赞 回复
分享
发布于 2019-08-23 22:51
跑了一下还真是
点赞 回复
分享
发布于 2019-08-23 22:53
看样子出这题的是传说中的扫地僧
点赞 回复
分享
发布于 2019-08-23 22:55
课堂练习题
点赞 回复
分享
发布于 2019-08-23 23:05
为啥呀
点赞 回复
分享
发布于 2019-08-23 23:09
可能在虚函数表中找虚函数是按其在类中申明的顺序做位置偏移的。把B中任意一个虚函数放到第一个,都会调用这第一个位置的虚函数。
点赞 回复
分享
发布于 2019-08-23 23:10
指针可以调用不涉及数据成员的成员函数所以第一个调用了
点赞 回复
分享
发布于 2019-08-24 00:26
第二个搞不明白。
点赞 回复
分享
发布于 2019-08-24 00:31
这个简直了,收藏了
点赞 回复
分享
发布于 2019-08-24 01:14
12楼应该正解。A::f1是静态绑定的而A::f2得动态绑定。A::f3也是及静态绑定。在程序编译时,就已经确定了函数的地址
点赞 回复
分享
发布于 2019-08-24 10:58
点赞 回复
分享
发布于 2019-08-24 13:11

相关推荐

8 48 评论
分享
牛客网
牛客企业服务