• 【笔试题】【day16】


    目录

    第一题(虚表指针的位置)

    第二题(私有继承的权限问题)

    第三题(运行时多态和编译时多态)

    第四题(多态的条件)

    第五题(多态+32位下指针大小)


    第一题(虚表指针的位置)

    代码执行后,a和b的值分别为?

    1. #include
    2. using namespace std;
    3. class Test{
    4. public:
    5. int a;
    6. int b;
    7. virtual void fun() {}
    8. Test(int temp1 = 0, int temp2 = 0)
    9. {
    10. a=temp1 ;
    11. b=temp2 ;
    12. }
    13. int getA()
    14. {
    15. return a;
    16. }
    17. int getB()
    18. {
    19. return b;
    20. }
    21. };
    22. int main()
    23. {
    24. Test obj(5, 10);
    25. // Changing a and b
    26. int* pInt = (int*)&obj;
    27. *(pInt+0) = 100;
    28. *(pInt+1) = 200;
    29. cout << "a = " << obj.getA() << endl;
    30. cout << "b = " << obj.getB() << endl;
    31. return 0;
    32. }

    A 200 10
    B 5 10
    C 100 200
    D 100 10

    首先我们创建了一个Test类型的对象,然后将其地址强制转换成int*赋值给了pInt,也就是得到了起始位置的4个字节的地址(32)位

    如果没有虚函数的话,也就是将下面这行代码注释掉

     

    我们的a和b刚好是在我们的对象前面的两个成员,

    所以*(pInt+0)其实就是我们的a的值,我们将其修改为100

    *(pInt+1)其实就是我们的b的值,我们将其修改为200

    但是有了这里的虚函数的话

    我们的对象的首位置是我们的虚表指针

    然后+1之后的修改,实际上修改的是我们的a成员

    也就是我们这里将我们的虚表赋值为了100,然后将我们的a成员赋值为了200

    然后我们的b成员还是原来的10

    由于这里没有访问虚函数,所以没有报错,但实际上如果通过多态访问虚函数表,就会报错,因为我们的虚表指针已经不能找到我们正确的虚表了 

    A

    第二题(私有继承的权限问题)

    下列程序的输出结果:

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. void print()
    7. {
    8. cout << "A:print()";
    9. }
    10. };
    11. class B: private A
    12. {
    13. public:
    14. void print()
    15. {
    16. cout << "B:print()";
    17. }
    18. };
    19. class C: public B
    20. {
    21. public:
    22. void print()
    23. {
    24. A:: print();
    25. }
    26. };
    27. int main()
    28. {
    29. C b;
    30. b.print();
    31. }

    A A:print()
    B B:print()
    C 编译出错

    B继承A,但是一个私有继承

    C共有继承B

    我们这里创建了一个C的对象,想要去调用A的方法

    程序会出错,因为B私有继承A,那么A中的所用成员在B中表现为私有成员

    那我们的C类是B类的子类,子类没有办法访问父类的私有成员。 

    C

    第三题(运行时多态和编译时多态)

    下面关于多态性的描述,错误的是() 

    A C++语言的多态性分为编译时的多态性和运行时的多态性
    B 编译时的多态性可通过函数重载实现
    C 运行时的多态性可通过模板和虚函数实现
    D 实现运行时多态性的机制称为动态绑定

    C中的模板和多态没有关系,模板是为了实现泛型编程,这两个不是同一个机制

    C

    第四题(多态的条件)

    写出下面程序的输出结果

    1. #include
    2. class A
    3. {
    4. public:
    5. void FuncA()
    6. {
    7. printf( "FuncA called\n" );
    8. }
    9. virtual void FuncB()
    10. {
    11. printf( "FuncB called\n" );
    12. }
    13. };
    14. class B : public A
    15. {
    16. public:
    17. void FuncA()
    18. {
    19. A::FuncA();
    20. printf( "FuncAB called\n" );
    21. }
    22. virtual void FuncB()
    23. {
    24. printf( "FuncBB called\n" );
    25. }
    26. };
    27. void main( void )
    28. {
    29. B b;
    30. A *pa;
    31. pa = &b;
    32. A *pa2 = new A;
    33. pa->FuncA(); //( 3)
    34. pa->FuncB(); //( 4)
    35. pa2->FuncA();//( 5)
    36. pa2->FuncB();
    37. delete pa2;
    38. }

    A FuncA called FuncB called FuncA called FuncB called
    B FuncA called FuncBB called FuncA called FuncB called
    C FuncA called FuncBB called FuncAB called FuncBB called
    D FuncAB called FuncBB called FuncA called FuncB called

    创建一个子类对象b

    父类指针指向子类对象pa

    父类指针指向父类对象pa2

    pa->FuncA()由于我们的pa是父类指针指向子类对象,但是父类的FuncA()中并没有写virtual,所以不满足多态的条件,直接调用父类的FuncA()方法,打印FuncA called

    pa->FuncB()由于这里是父类的指针指向子类的对象并且父类中的FuncB前面有virtual,满足多态的条件,所以我们这里直接调用子类的FuncB,打印FuncBB called 

    pa2->FuncA 这里的pa2是父类的指针指向父类的对象,所以它是直接调用父类的FuncA方法,打印FuncA called

     pa2->FuncB 这里的pa2是父类的指针指向父类的对象,不满足多态的条件,所以它是直接调用父类的FuncB方法,打印FuncB called

    第五题(多态+32位下指针大小)

    1. #include
    2. using namespace std;
    3. class Base
    4. {
    5. public:
    6. virtual int foo(int x)
    7. {
    8. return x * 10;
    9. }
    10. int foo(char x[14])
    11. {
    12. return sizeof(x) + 10;
    13. }
    14. };
    15. class Derived: public Base
    16. {
    17. int foo(int x)
    18. {
    19. return x * 20;
    20. }
    21. virtual int foo(char x[10])
    22. {
    23. return sizeof(x) + 20;
    24. }
    25. } ;
    26. int main()
    27. {
    28. Derived stDerived;
    29. Base *pstBase = &stDerived;
    30. char x[10];
    31. printf("%d\n", pstBase->foo(100) + pstBase->foo(x));
    32. return 0;
    33. }

     在32位环境下,以上程序的输出结果是?

    A 2000
    B 2004
    C 2014
    D 2024

    我们首先创建了一个子类对象,然后用父类的指针指向子类的对象

    父类的指针访问foo(100),这里满足了多态调用的条件,调用的是子类的方法,也就是我们下面两个中,更下面的这个方法

     

     100*20=2000

    这里只要传入一个指针数组就可以调用这个方法,跟你是不是14没有关系

     

    这里我们是父类的指针,并且不满足多态的条件,所以我们直接调用的就是父类的foo方法。因为我们在32位的系统下,我们的指针的大小为4个字节,所以这里返回的是

     4+10=14

    最后我们将这两个值加起来也就是2000+14=2014 

    C

  • 相关阅读:
    R语言绘制散点密度图ggdentity
    12、初识表单POST和get提交
    爬虫破解:解决CSRF-Token反爬问题 - 上海市发展和改革委员会
    JAVAWEB,tomcat,MVC
    【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷A
    nginx初识
    ResourceManager启动报错:Queue configuration missing child queue names for root【已解决】
    Zookeeper-3.8.0单台、集群环境搭建
    【ESP 保姆级教程】疯狂Node.js服务器篇 ——本地部署MQTT服务器以及剖析MQTT过程
    cocos2d-lua:骨骼动画的使用
  • 原文地址:https://blog.csdn.net/weixin_62684026/article/details/127581746