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

来源:互联网 发布:ug编程实例教程零件 编辑:程序博客网 时间:2024/05/28 04:53

可能是因为光是看书,关于看到的知识点也不会去深思各种各样的场景去构造,导致遇到一些很基础的问题都会犯二,写此篇博客,特警示自己:
学知识,最重要的是思考!!!

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

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;}

这里写图片描述

不知道你看完之后是什么感受?你有没有全部答对呢?如果全部答对了,那么说明你对于继承/多态理解的特别透彻了,希望你不要像我一样惨~

2 0