• 详细说明C++笔试题,调查超载、盖、多态


        C++可见版本,他说,这本书是采访的主题,调查超载、盖、多态性等概念,比较有代表性的。今天上午,远程辅导 Yan Wang 学生们学习 Qt 时还觉得这个话题,假设你能正确地理解这一主题,注意对于 C++ 该函数重载、盖、虚函数、有了正确的认识和多态性。呢。再来学习 Qt 就顺风顺水了。

        题目是酱紫的:

    #include <iostream>
    #include <string>
    using namespace std;
    class A
    {
    protected:
        int m_data;
    public:
        A(int data = 0)
        {
            m_data = data;
        }
        int GetData()
        {
            return doGetData();
        }
        virtual int doGetData()
        {
            return m_data;
        }
    };
    class B : public A
    {
    protected:
        int m_data;
    public:
        B(int data = 1)
        {
            m_data = data;
        }
        int doGetData()
        {
            return m_data;
        }
    };
    class C : public B
    {
    protected:
        int m_data;
    public:
        C(int data = 2)
        {
            m_data = data;
        }
    };
    void main()
    {
        C c(10);
       
        cout << c.GetData() << endl;
        cout << c.A::GetData()<< endl;
        cout << c.B::GetData()<< endl;
        cout << c.C::GetData()<< endl;
       
        cout << c.doGetData()<< endl;
        cout << c.A::doGetData()<< endl;
        cout << c.B::doGetData()<< endl;
        cout << c.C::doGetData()<< endl;
    }

        程序执行后的输出结果是什么?

        答案是:1 1 1 1 1 0 1 1

        追问一下,去掉 A 类中 doGetData() 函数的 virtual 修饰,程序执行后的输出结果是什么?

        答案是:0 0 0 0 1 0 1 1


        说说我对这个题目的理解。

        首先我们从对象的角度来看一下。
        先看 main() 函数中构造 c 对象的语句:
        

    C c(10);

        这句产生以下的效果:

    • c.m_data = 10;
    • ((B)c).m_data = 1;
    • ((A)c).m_data = 0;

        为什么呢?

        C c(10); 这行代码,定义了 c 对象。但实际上内存中有三个对象:

    1.     class C 的实例对象,即 c
    2.     由于 C 是 B 的派生类,会产生一个 class B 实例对象,即 (B)c
    3.     由于 B 是 A 的派生类。会产生一个 A 实例对象,即 (A)c

        每一个对象都有 m_data 成员变量, 依据继承关系,子类覆盖父类的同名成员(变量、函数)。 c 对象中实际上有三个同名的 m_data 变量。你通过不同的身份去看,会看到不同的 m_data 。

        C 对象生成时。调用 B 、A 类的构造函数,对 B 、 A 初始化,结果就是:

    •     c 对象的 m_data = 10;
    •     ((B)c) 对象的 m_data = 1; 
    •     ((A)c) 对象的 m_data = 0.

        这就是我们一開始给出的效果。


        明确了对象的关系和 m_data 成员的值。咱们再来看 GetData() 函数。

        GetData() 函数是 class A 的一个普通方法。依据继承关系, B 、 C 类都可以訪问 GetData() 方法,由于 B 、 C 没有重写 GetData() 。所以通过 B 、 C 的对象訪问 GetData() ,訪问的都是 A 的 GetData() 方法。

        在 GetData() 中。调用了 doGetData() ,注意了,这是个虚函数!假设 A 的后裔重写了 doGetData() 函数,那么这里实际上会调用到继承关系上处于最底层的那个类的 doGetData() 函数,这就是虚函数和多态的概念。如你所见。 B 重写了 doGetData() 函数,所以当你调用 c.GetData() 。 B 的 doGetData() 会被调用, ((B)c).m_data 被返回。

    事实上在 Qt 中,这样的使用方法比比皆是。

        好啦。以下分析 main() 函数的输出结果。

        doGetData() 带 virtual keyword

        c.A::GetData() / c.GetData() / c.B::GetData() / c.C::GetData()

        这些语句,都是调用 A::GetData() 。终于都调用 ((B)c).doGetData(), 就是B::doGetData() ,訪问的是 B 的对象,它的 m_data = 1 。所以 doGetData() 返回 1 。终于 GetData() 返回 1 。
       
        C 类未定义 doGetData() 函数,c.doGetData() 等同于 ((B)c).doGetData() , 訪问的是 B 的对象,它的 m_data = 1 。所以 c.doGetData() 结果是 1 。

        c.A::doGetData() 。类域作用符限定了调用 A::doGetData()。訪问 A 的对象,返回 ((A)c).m_data = 0 。

        c.B::doGetData() / c.C::doGetData() 终于都是訪问 B 对象的 doGetData() 方法, 返回都是 1 。

        所以 doGetData() 带 virtual keyword,程序输出 1 1 1 1 1 0 1 1 。

        去掉 doGetData() 的 virtual keyword  

        由于 GetData() 是 A 类的方法,而 doGetData() 不是虚函数。 A 类的 GetData() 内调用的 doGetData() 方法仅仅可能是 A 的对象的方法,((A)c).m_data = 0 ,所曾经四个cout结果都是 0 。

       
        c.doGetData() ,C 的对象内没有实现这个函数,调用父类的,即 B 的对象的 doGetData() 方法。訪问的 m_data 是 ((B)c) 对象的,是 1 。

        c.A::doGetData() ,调用 A 的方法。訪问 A 的对象 ((A)c).m_data ,结果是 0 。

        c.B::doGetData() / c.C::doGetData() 。调用 B 的方法。訪问 B 的对象 ((B)c).m_data 。结果为 1 。


        所以,终于结果是:0 0 0 0 1 0 1 1

        

        我不知道说清楚没有什么?


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    第八篇:Vue组件传参
    第七篇:Vue的路由逻辑跳转
    第六篇:组件数据局部化处理
    第五篇:Vue项目的初始化
    第四篇:Vue的项目开发
    第三篇:Vue指令
    第二篇:Vue实例成员
    第一篇:Vue基础
    第六篇:js对象,类和函数补充
    AngularJS之jeDate日期控件基本使用
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4683507.html
Copyright © 2020-2023  润新知