zoukankan      html  css  js  c++  java
  • 同名覆盖引发的问题

    • 父子间的赋值兼容
    1. 子类对象可以直接赋值给父类对象
    2. 子类对象可以直接初始化父类对象
    3. 父类指针可以直接指向子类对象
    4. 父类引用可以直接引用子类对象
    • 实验
    // 同名覆盖引发的问题.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    #include <iostream>
    class Parent
    {
    public:
        int mv;
        Parent()
        {
            mv = 0;
        }
        void add(int x)
        {
            mv = mv + x;
        }
        void add(int x,int y)
        {
            mv = mv + x + y;
        }
    };
    class Child :public Parent
    {
    public:
        int mi;
        Child()
        {
            mi = 0;
        }
        void add(int x, int y, int z)
        {
            mi = mi + x + y + z;
        }
    };
    int main()
    {
        Child c;
        Parent p;
        //子类对象可以直接赋值给父类对象
        p = c;
        //子类对象可以直接初始化父类对象
        Parent p1(c);
        //父类指针可以直接指向子类对象
        Parent* p2 = &c;
        //父类引用可以直接引用子类对象
        Parent& p3 = c;
        //没有发生同名覆盖
        p2->add(1);
        p2->add(2, 3);
        p2->mv = 5;
        //编译报错,不能引用子类的成员
        // p3.add(4, 5, 6);
        // p3.mi = 100;
    }
    • 当使用父类指针(引用)指向子类对象时
    1. 子类对象退化为父类对象
    2. 只能访问父类中定义的成员
    3. 可以直接访问被子类覆盖的同名成员
    • 特殊的同名函数
    1. 子类中可以重定义父类中已经存在的成员函数
    2. 这种重定义发生在继承中,叫做函数重写
    3. 函数重写是同名覆盖的一种特殊情况
    class Parent
    {
    public:
        void printf()
        {
            printf("I'm Parent");
        }
    };
    class Child :public Parent
    {
    public:
        void printf()
        {
            printf("I'm Parent");
        }
    };
    • 思考:当函数重写遇上赋值兼容会发生什么?
    • 实验:
    #include <iostream>
    #include <string>
    using namespace std;
    class Parent
    {
    public:
        int mv;
        Parent()
        {
            mv = 0;
        }
        void add(int x)
        {
            mv = mv + x;
        }
        void add(int x,int y)
        {
            mv = mv + x + y;
        }
        void printf()
        {
            cout << "I'm Parent" << endl;
        }
    };
    class Child :public Parent
    {
    public:
        int mi;
        Child()
        {
            mi = 0;
        }
        void add(int x, int y, int z)
        {
            mi = mi + x + y + z;
        }
        void print()
        {
            cout << "I'm Child" << endl;
        }
    };
    void How_to_printf(Parent*p)
    {
        p->printf();
    }
    int main()
    {
        Child c;
        Parent p;
        How_to_print(&c);  //Expected to printf:I'm Child
        How_to_print(&p);  //Expected to printf:I'm Parent
    }
    • 运行结果
    I'm Parent
    I'm Parent
    • 问题分析
    在编译期间,编译器只能根据指针得类型判断所指向的对象,根据赋值兼容,编译器认为父类指针指向的是父类对象,因此,编译结果只可能是调用父类中定义的同名函数
    void How_to_print(Parent*p)
    {
        p->printf();
    }
    在编译这个函数的时候,编译器不可能知道指针p究竟指向了什么。但是编译器没有理由报错。于是,编译器认为最安全的做法是调用父类的print函数,因为父类和子类肯定有相同的print函数
    • 问题:编译器的处理方法是合理的吗?是期望的吗?
    • 答:是合理的,但并不是我们所期望的。
    • 小结
    1. 子类对象可以当作父类对象使用(赋值兼容)
    2. 父类指针可以正确的指向子类对象
    3. 父类引用可以正确的代表子类对象
    4. 子类中可以重写父类中的成员函数
     
     
     
     
     
     
     
     
     
    主要记录的是学习听课的笔记
  • 相关阅读:
    浏览网页时看到一个把字符串偶数位转化为大写字母的问题,小小白也来班门弄斧尝试一下。
    MFC的连续存储 永久保存(串行化)两篇
    MFC打印和打印预览功能
    桌面linux系统和嵌入式linux系统的不同点
    Ubuntu 和linux的关系
    YUV YPbPr YCbCr CCIR 601 CCIR 656
    推荐几个学习linux的国外著名论坛网站
    使Android开发方便快捷的8个好工具
    VMware网络配置详解
    DSP 定点小数运算
  • 原文地址:https://www.cnblogs.com/chengeputongren/p/12245862.html
Copyright © 2011-2022 走看看