您的位置:首页 > 职场人生

关于对象模型的几个面试题(很基础,但坑较多)

2017-04-08 00:09 423 查看
可能是因为光是看书,关于看到的知识点也不会去深思各种各样的场景去构造,导致遇到一些很基础的问题都会犯二,写此篇博客,特警示自己:

学知识,最重要的是思考!!!

如果关于对象模型你还有那么一点兴趣,那么可以继续向下看,看看自己是否可以完全答对。。。

1.面试题(选择题):

下面我贴出的是主要的代码片,头文件以及using namespace std;需要自行添加哦!

class A
{
public :
A()
:_a(1)
{}
virtual void FunTestA()
{}
int _a;
};

class B
{
public:
B()
:_b(2)
{}
virtual void FuntestB()
{}
int _b;
};

class C :public A, public B
{
public :
C()
:A()
, B()
, _c(3)
{}
int _c;
};

void Fun()
{
C c;
cout << sizeof(c) << endl;
A* pA = &c;
B* pB = &c;
C* pC = &c;
}

int main()
{
Fun();
return 0;
}


选项:

A pA、pB、pC的取值相同

B、 pC 和 pA不相同

C、pB和pC不相同

D、pC不等于pA,也不等于pB。



C类对象模型:



解析:在继承体系中,当用一个基类的指针或引用指向派生类对象时(赋值兼容规则),这时会将派生类对象的地址偏移一个合适偏移量,因为派生类对象也是一个基类对象,实际也就是让基类指针指向派生类中属于基类的那部分。所以一般先继承的那个类(基类)的指针和派生类的对象的地址相等。不知道你有没有听懂呢?(无奈脸)

2.问下列程序会输出什么?

1)A类和B类是两个不相关的类

class A
{
public :
A()
{
m_a = 1;
m_b = 2;
}

void fun()
{
cout << m_a <<"  "<< m_b << endl;
}
private :
int m_a;
int m_b;
};

class B
{
public :
B()
{
m_c = 3;
}

void fun()
{
cout << m_c << endl;
}

private :
int m_c;
};

void Fun()
{
A a;
B* pb = (B*)(&a);
pb->fun();
}

int main()
{
Fun();
return 0;
}


A类和B类没有关系,所以pb肯定调用的是B类的fun函数,但是pb又是被强制指向A类对象的,

那么肯定会打印前A类对象前四个字节的值,也就是1。(因为B类大小就是4个字节)。

图形解析如下:



2)B类公有继承自A类时,程序会输出什么?

class A
{
public :
A()
{
m_a = 1;
m_b = 2;
}

void fun()
{
cout << m_a <<"  "<< m_b << endl;
}
private :
int m_a;
int m_b;
};

class B:public A
{
public :
B()
:A()
{
m_c = 3;
}

void fun()
{
cout << m_c << endl;
}

private :
int m_c;
};

void Fun()
{
A a;
B* pb = (B*)(&a);//切记:这里是派生类的指针指向基类对象
pb->fun();
}

int main()
{
Fun();
return 0;
}


解析:pb仍然会去调用B类的fun函数,而B类的fun函数需要打印m_c的值,对象a中并没有m_c,那块空间未定义,所以程序最终输出随机值或者程序崩溃。

图解如下:



3).B公有继承自A,且将A中的fun函数定义为虚函数后

输出结果为: 1 2

class A
{
public :
A()
{
m_a = 1;
m_b = 2;
}

virtual void fun()//虚函数
{
cout << m_a <<"  "<< m_b << endl;
}
private :
int m_a;
int m_b;
};

class B:public A
{
public :
B()
:A()
{
m_c = 3;
}

void fun()//重写
{
cout << m_c << endl;
}

private :
int m_c;
};

void Fun()
{
A a;
B b;
B* pb = (B*)(&a);//切记:这里是派生类的指针指向基类对象,不会形成多态
pb->fun();//在A类的虚表内找fun函数(调用的是A类的fun函数),输出1和2
}

int main()
{
Fun();
return 0;
}


对象模型:



4)B公有继承自A,且A中的fun为普通函数,仅将B类fun函数定义为虚函数.

输出什么?——–>程序崩溃

class A
{
public :
A()
{
m_a = 1;
m_b = 2;
}

void fun()//普通函数
{
cout << m_a <<"  "<< m_b << endl;
}
private :
int m_a;
int m_b;
};

class B:public A
{
public :
B()
:A()
{
m_c = 3;
}

virtual void fun()//虚函数
{
cout << m_c << endl;
}

private :
int m_c;
};

void Fun()
{
A a;
B b;
B* pb = (B*)(&a);
pb->fun();//要去a对象的前四个字节取虚表地址,从而去找fun函数,可惜a对象中并没有虚表,所以程序崩溃
}

int main()
{
Fun();
return 0;
}




不知道你看完之后是什么感受?你有没有全部答对呢?如果全部答对了,那么说明你对于继承/多态理解的特别透彻了,希望你不要像我一样惨~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  对象模型