码迷,mamicode.com
首页 > 编程语言 > 详细

C++继承、虚函数处的面试题

时间:2016-04-29 15:44:50      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:

        昨天,收到 SenseTime公司面试官的电话面试(一天面了三家公司,收获挺多的),通话时间将近1个半小时,面试过程中暴露出很多知识上的漏洞,本篇文章针对面试过程中继承以及虚函数方面的知识做一总结,查缺补漏,希望对大家有帮助。

单继承下的虚函数表

//单继承下虚函数表:是如何组织的
class A{
public:
	virtual void func(){
		cout << "A::func" << endl;
	}
	virtual void funcA(){
		cout << "A::funcA" << endl;
	}
};

class B:public A{
public:
	virtual void func(){
		cout << "B::func" << endl;
	}
	virtual void funcB(){
		cout << "B::funcB" << endl;
	}
};


class C:public A{
public:
	virtual void func(){
		cout << "C::func" << endl;
	}
	virtual void funcC(){
		cout << "C::funcC" << endl;
	}
};

typedef void (*FUNC)();
int main()
{
	A a;
	B b;
	C c;
	cout << "A::虚表:" << endl;
	((FUNC)(*(int *)(*(int*)(&a))))();
	((FUNC)(*((int*)(*(int*)(&a)) + 1)))();
	cout << "-------------------------------------" << endl;

	cout << "B::虚表:" << endl;
	((FUNC)(*(int *)(*(int*)(&b))))();
	((FUNC)(*((int*)(*(int*)(&b)) + 1)))();
	((FUNC)(*((int*)(*(int*)(&b)) + 2)))();
	cout << "-------------------------------------" << endl;

	cout << "C::虚表:" << endl;
	((FUNC)(*(int *)(*(int*)(&c))))();
	((FUNC)(*((int*)(*(int*)(&c)) + 1)))();
	((FUNC)(*((int*)(*(int*)(&c)) + 2)))();
	system("pause");
	return 0;
}
技术分享

问题1:三个类中都有虚函数,所以三个类均有各自独立的虚函数表

问题2:三个虚函数表的组织情况,如上图所示

问题3:B、C各自拥有自己的虚函数表,互不影响

问题4:类的对象只存储指向虚函数表的指针vfptr(一般存储在对象内存布局的最前面),虚函数表只有一份,为所有对象所共享,vtable在Linux/Unix中存放在可执行文件的只读数据段中(rodata),而微软的编译器将虚函数表存放在常量段点击打开链接

typedef void(*FUNC)();
class A{
public:
	virtual void func(){
		cout << "A::func" << endl;
	}
	virtual void funcA(){
		cout << "A::funcA" << endl;
	}
private:
	int a;
};
class B{
public:
	virtual void func(){
		cout << "B::func" << endl;
	}
	virtual void funcB(){
		cout << "B::funcB" << endl;
	}
private:
	int b;
};
class C :public A, public B{
public:
	virtual void func(){
		cout << "C::func" << endl;
	}
	virtual void funcC(){
		cout << "C::funcC" << endl;
	}
private:
	int c;
};typedef void(*FUNC)();
class A{
public:
	virtual void func(){
		cout << "A::func" << endl;
	}
	virtual void funcA(){
		cout << "A::funcA" << endl;
	}
private:
	int a;
};
class B{
public:
	virtual void func(){
		cout << "B::func" << endl;
	}
	virtual void funcB(){
		cout << "B::funcB" << endl;
	}
private:
	int b;
};
class C :public A, public B{
public:
	virtual void func(){
		cout << "C::func" << endl;
	}
	virtual void funcC(){
		cout << "C::funcC" << endl;
	}
private:
	int c;
};


多继承条件下的虚函数表

//多继承条件下的虚函数表
void test()
{
	C c;
	cout << "多继承条件下的虚函数表:" << endl;
	cout << "------------------------" << endl;
	((FUNC)(*((int*)(*(int *)(&c)))))();
	((FUNC)(*((int*)(*(int*)(&c)) + 1)))();
	((FUNC)(*((int*)(*(int*)(&c)) + 2)))();
	cout << "------------------------" << endl;
	((FUNC)(*(int*)(*((int*)(&c) + 2))))();
	((FUNC)(*((int*)(*((int*)(&c) + 2)) + 1)))();
}


技术分享

对象C的内存空间分布如下图所示:

技术分享

多继承条件下,基类指针指向派生类后,基类指针所能访问的函数

//多继承条件下,基类指针指向派生类后,基类指针所能访问的函数
void test1()
{
	C c;
	A *pa = &c;
	B *pb = &c;
	C *pc = &c;
	cout << "基类指针pa所能调用的函数:" << endl;
	pa->func();
	pa->funcA();
	//pa->funcB();error:提示类A没有成员funcB、funcC  -->受到类型的限制
	//pa->funcC();error


	cout << "基类指针pb所能调用的函数:" << endl;
	pb->func();
	pb->funcB();
	//pb->funcA();error
	//pb->funcC();error

	cout << "派生类指针pc所能调用的函数:" << endl;
	pc->func();
	pc->funcA();
	pc->funcB();
	pc->funcC();
}
技术分享

问题1:pa和pc的值相同,都是对象c的首地址,pb和pa至今相差四个字节(int  a造成的-->观察上图的内存空间分配)

问题2:基类指针指向派生类的对象,通过该基类指针所能访问的函数受类型的限制(运行时调用哪个函数受多态的影响)

技术分享

3:由于多态,会访问C类的func

4:通过加作用域:pa->A::func()


多继承条件下,基类指针指向派生类对象后,基类指针之间强制类型转化之后,所能访问的函数

void test2()
{
	C c;
	A *pa = &c;
	B *pb = &c;
	C *pc = &c;

	pa = reinterpret_cast<A *>(pb);
	pa->func();
	pa->funcA();      

	//pb = reinterpret_cast<B *>(pa);
	//pb->func();
	//pb->funcB();

	//pa = reinterpret_cast<A *>(pc);
	//pa->func();
	//pa->funcA();

}
技术分享

结果很奇怪(查看汇编分析)

技术分享


最后一个简单地问题如下

技术分享

相信你经过以上问题的分析,一定会回答出来(答案已经在图里面了^_^)

C++继承、虚函数处的面试题

标签:

原文地址:http://blog.csdn.net/zongyinhu/article/details/51276806

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!