继承和多态相关的练习

目录

一、概念题

二、程序题


 


一、概念题

  1. 下面哪种面向对象的方法可以让你变得富有()。

    A、继承 B、封装 C、多态 D、抽象

  2. ()是面向对象程序设计语言中的一种机制,这种机制实现了方法的定义与具体的对象无关,而对方法的调用则可以关联到具体的对象。

    A、继承 B、模板 C、对象的自身引用 D、动态绑定

  3. 面向对象设计中的继承和组合,下面说法错误的是()。

    A、继承允许我们覆盖重写父类的实现细节,父类的实现对于子类是可见的,是一种静态复用,也称为白盒复用

    B、组合的对象不需要关心各自的实现细节,之间的关系是在运行时才确定的,是一种动态复用,也称为黑盒复用

    C、优先使用继承,而不是组合,是面向对象设计的第二原则

    D、继承可以使子类能自动继承父类的接口,但在设计模式中认为这是一种破坏父类的封装性的表现

  4. 以下关于纯虚函数的说法,正确的是()。

    A、声明纯虚函数的类不能实例化对象

    B、声明纯虚函数的类是虚基类

    C、子类必须实现基类的纯虚函数

    D、纯虚函数必须是空函数

  5. 关于虚函数的描述正确的是()。

    A、派生类的虚函数与基类的虚函数具有不同的参数个数和类型

    B、内联函数不能是虚函数

    C、派生类必须重新定义基类的虚函数

    D、虚函数可以是一个 static 型的函数

  6. 关于虚表说法正确的是()。

    A、一个类只能有一个虚表

    B、基类中有虚函数,如果子类中没有重写基类的虚函数,此时子类与基类共用同一张虚表

    C、虚表是在运行期间动态生成的

    D、一个类的不同对象共享该类的虚表

  7. 假设 A 类中有虚函数,B 继承自 A,B 重写 A 中的虚函数,也没有定义任何虚函数,则()。

    A、A 类对象的前 4 个字节存储虚表地址,B 类对象的前 4 个字节不是虚表地址

    B、A 类对象和 B 类对象的前 4 个字节存储的都是虚基表的地址

    C、A 类对象和 B 类对象的前 4 个字节存储的虚表地址相同

    D、A 类和 B 类虚表中虚函数个数相同,但 A 类和 B 类使用的不是同一张虚表

参考答案

  1. A

  2. D

  3. C

  4. A

  5. B

    • 内联函数不能是虚函数。因为内联函数是一个静态行为(编译器在预处理阶段将内联函数的函数体替换到函数调用处),而虚函数是一个动态行为(编译器并不知道要调用的是基类的虚函数,还是派生类的虚函数),它们之间是存在矛盾的

      我们之所以能看到一些像内联函数的虚函数,是因为某个函数是否是内联函数是由编译器决定的,我们只能向编译器建议某个函数可以是内联函数,但编译器有自己的判断法则

    • 静态成员函数不能是虚函数。因为静态成员函数没有 this 指针,而对于虚函数,它的调用恰恰是使用了 this 指针(在有虚函数的类实例中,this 指针调用虚函数表指针,在虚函数表中找到需要调用的虚函数地址)

  6. D

    基类和派生类不共用同一张虚表,同一类的不同对象共用同一张虚表

    #include <iostream>
    using namespace std;
    ​
    class A
    {
    public:
        virtual inline void func() 
        {
            cout << "A::func" << endl;
        }
    protected:
        int _a = 1;
    };
    ​
    class B : public A
    {
    protected:
        int _b = 2;
    };
    ​
    int main()
    {
        A a;
        B b1;
        B b2;
        return 0;
    }

  7. D


二、程序题

  1. 下面程序输出结果是什么?

    #include<iostream>
    using namespace std;
    ​
    class A 
    {
    public:
        A(const char* s) { cout << s << endl; }
        ~A() { }
    };
    ​
    class B : virtual public A
    {
    public:
        B(const char* s1, const char* s2) : A(s1) { cout << s2 << endl; }
    };
    ​
    class C : virtual public A
    {
    public:
        C(const char* s1, const char* s2) : A(s1) { cout << s2 << endl; }
    };
    ​
    class D : public B, public C
    {
    public:
        D(const char* s1, const char* s2, const char* s3, const char* s4)
            : B(s1, s2), C(s1, s3), A(s1)
        {
            cout << s4 << endl;
        }
    };
    ​
    int main()
    {
        D* p = new D("class A", "class B", "class C", "class D");
        delete p;
        return 0;
    }

    A、class A class B class C class D

    B、class D class B class C class A

    A、class D class C class B class A

    A、class A class C class B class D

  2. (多继承中指针偏移问题)下面说法正确的是()。

    class Base1 { public: int _b1; };
    ​
    class Base2 { public: int _b2; };
    ​
    class Derive : public Base1, public Base2 { public: int _d; };
    ​
    int main() 
    {
        Derive d;
        Base1* p1 = &d;
        Base2* p2 = &d;
        Derive* p3 = &d;
        return 0;
    }

    A、p1 == p2 == p3 B、p1 < p2 < p3 C、p1 == p3 != p2 D、p1 != p2 != p3

  3. 下面程序输出结果是什么?

    #include <iostream>
    ​
    class A
    {
    public:
        virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
    ​
        virtual void test() { func(); }
    };
    ​
    class B : public A
    {
    public:
        void func(int val = 0) { std::cout << "B->" << val << std::endl; }
    };
    ​
    int main()
    {
        B* p = new B;
        p->test();
        return 0;
    }

    A、A->0 B、B->1 C、A->1 D、B->0 E、编译错误 F、以上都不正确

参考答案

  1. A

  2. C

  3. B

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值