• 成员函数覆盖和重写


    函数覆盖:

    发生在使用父类指针或引用指向子类对象时:  

      1. 子类对象退化为父类对象

      2. 只能访问父类中定义的成员。

      3. 可以直接访问被子类覆盖的同名成员。

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Parent
    {
    public:
        void func(int x)
        {}
        void func(int x, int y)
        {}
    };
    
    class Child : public Parent
    {
    public:
        void func(int x, int y, int z)
        {}
    };
    
    int main()
    {
        Parent p;
        Child c;
        
        p = c;                    // 用子类赋值给父类  
        Parent p1(c);             // 用子类初始化父类
          
        Parent& cite_p = c;       // 父类引用子类    编译器只能根据指针所指向的类型来判断所指向的对象的类型-->也就是Parent
        Parent* point_p = &c;     // 父类指向子类    指针所指向的类型(parent)来判断所指向的对象的类型(parent)
        
        cite_p.add(1);           // 子类退化为父类
        cite_p.add(1,1);          // 子类退化为父类
        cite_P.add(1,1,1)         // error 子类退化为父类,无法引用子类函数
    
        point_p.add(1);          // 子类退化为父类
        point_p.add(1,1);        // 子类退化为父类
        point_p.add(1,1,1)       // error 子类退化为父类,无法通过指针访问子类函数  
        return 0;
    }

    函数重写:

      1. 子类中重定义了与父类完全相同的函数。

      2. 重定义发生在继承中时就叫重写。

      3. 函数重写只是一种特殊的同名覆盖(函数名和参数完全相同的覆盖)。

      4. 依旧可以通过作用域分辨符来访问被重写的函数。

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Parent
    {
    public:
        void print()
        {
            cout << "I'm Parent." << endl;
        }
    };
    
    class Child : public Parent
    {
    public:
        void print()   // 函数重写
        {
            cout << "I'm Child." << endl;
        }
    };
    
    void how_to_print(Parent* p)
    {
        p->print();
    }
    
    int main()
    {
        Parent p;
        Child c;
        
        how_to_print(&p);    //  I'm Parent.  退化为父类指针,之可以访问父类的成员函数和成员变量。
        how_to_print(&c);    //  I'm Parent.  退化为父类的指针。函数重写却没有用,原因是指针所指向的类型(parent)来判断所指向的对象的类型(parent)
        c.Parent::print();   //  I'm Parent.  通过作用域访问符来访问被重写的函数
       c.print();           //  I'm Child.   函数覆盖
      return 0; }

    Java覆盖是:方法名相同,参数列表相同,返回值相同。

    C++覆盖是:方法名相同,       返回值相同。

    在Java中出现子类的方法的方法名与父类相同时,会继承父类的同名函数,子类可以访问。

    在C++中出现子类的函数的函数名与父类相同时,会覆盖父类的同名函数,子类无法访问。

    #include<iostream>
    
    using namespace std;
    
    class Parent
    {
    public:
        int add(int val1)
        {
            return (val1);
        }
    };
    
    class Child : public Parent
    {
    public:
        int add(int val1, int val2)
        {
            return (val1 + val2);
        }
        
        int add(int val1, int val2, int val3)
        {
            return (val1 + val2 + val3);
        }
    };
    
    int main(void)
    {
        Child c1;
        Child* c2 = new Child();
        cout << c1.add(1) << endl;   //error 函数同名但参数列表不同会隐藏父类同名函数
        return 0;
    }
    class Parent
    {
        public int add(int val1)
        {
            return (val1);
        }
    }
    
    class Child extends Parent
    {
        public int add(int val1, int val2)
        {
            return (val1 + val2);
        }
        
        public int add(int val1, int val2, int val3)
        {
            return (val1 + val2 + val3);
        }
    }
    
    public class Chapter8_1
    {
        public static void main(String[] args)
        {
            Child c = new Child();
            System.out.println(c.add(1));  //ok 同名函数但参数列表不同并不会隐藏
        }
    
    }

    由于编译器对指针的处理方式,所以当对重写后的函数进行指针访问时会出错。

    父子间的兼容性:

      1. 子类对象可以直接赋值给父类对象:Parent p; Child c; p = c;

      2. 子类对象可以直接初始化父类对象:Parent p(c);

      2. 父类对象可以直接引用子类对象:Parent& p = c;

      3. 父类对象可以直接指向子类对象:Parent* p = &c;

       以上是编译器将子类对象退化为父类对象,从而可以初始化父类。所以以上父类对象(指针,引用)只能访问父类的成员。

    问题: 子类可以重写父类的成员,根据兼容性使用父类指针后又无法访问重写的函数。

      可以通过强制转化将父类对象转化为子类对象。

      Child*  c = (static_cast*)<Child*>p;

  • 相关阅读:
    IP地址加时间戳加3位随机数
    你会想造一艘船吗?
    提问的智慧
    建造者模式
    设计模式(一)
    jeesite中activiti中的流程表梳理
    如何读书、学习?
    zxing生成高容错率二维码,以及添加文字
    LVM磁盘划分
    阿里云盘扩容(SUSE Linux下)
  • 原文地址:https://www.cnblogs.com/zsy12138/p/10848218.html
Copyright © 2020-2023  润新知