C++ 基类方法重载、重写、隐藏


C++ 基类方法重载、重写、隐藏


成员函数重载

  • 重载构成的条件是:在同一作用域下的函数,函数名相同,参数列表不同构成重载。
    class Base {
      public:
          Base(int data) :ma(data) { cout << "Base(int data)" << endl; }
          Base() = default;
          ~Base() { cout << "~Base()" << endl; }
    
          void show() { cout << "Base::show()" << endl; }
          void show(int val) { cout << "Base::show(int)" << endl; }
    
      protected:
          int ma;
    };
    
    class Deriver :public Base {
      public:
          Deriver(int data) :mb(data), Base(data) { cout << "Deriver(int data)" << endl; }
          ~Deriver() { cout << "~Deriver()" << endl; }
          
          void show(int a, int b, int c) { cout << "Deriver::show(int,int,int)" << endl; }
      private:
          int mb;
    };
    
  • 重载的原理:C++编译代码时生成的符号名由函数名+参数列表组成,所以只要生成的符号不一样,那么就可以重载,不会产生编译问题,与返回值无关
  • 重载成员函数是对于类内而言的:
    class A{
      public:
       void func();
       void func(int); // overload
       void func(double, double); // overload
    }
    
    A 中的三个 func 函数是重载 overload。

重写

  • 重写构成的条件:大前提,一个方法 A 在基类中是虚函数;子类中存在一个与父类的那个虚函数返回值、参数列表相同的函数 B ,则父类虚函数 A 被子类继承后被 B 函数覆盖;子类方法 B 此时也是一个虚函数。
    class Base {
    public:
        Base(int data) :ma(data) { cout << "Base(int data)" << endl; mc = data; }
        ~Base() { cout << "~Base()" << endl; }
    
        virtual void show() { cout << "Base::show()" << endl; } //在子类中被重写的show方法
        void show(int val) { cout << "Base::show(int)" << endl; } //被子类隐藏的show方法
        int mc;
    protected:
        int ma;
    };
    
    class Deriver :public Base {
    public:
        Deriver(int data) :mb(data), Base(data) { cout << "Deriver(int data)" << endl; }
        ~Deriver() { cout << "~Deriver()" << endl; }
        virtual void show(){ cout << "Deriver::show()" << endl; } //也是一个虚函数
    private:
        int mb;
    };
    
    
  • 基类的同名虚方法在派生类中被重新定义,称为重写 override:
    class A{
      public:
      	virtual void func();
    }
    class B : public A{
    	public:
    	  virtual void func(); // override
    }
    
    注意:虚函数重写时,派生类虚函数的返回类型要与基类一致,否则报 error: conflicting return type specified for virtual…,但是如果基类虚函数返回类型是基类指针或引用,派生类虚函数可以返回派生类指针或引用,这被称为返回类型协变
    class A{
      public:
      	virtual A func();
      	virtual A& func();
    }
    
    class B : public A{
    	public:
    		virtual B func(); // error!
    		virtual B& func(); // ok
    }
    

隐藏

  • 隐藏的构成条件:派生类中含有与基类同名的方法,编译器会优先选择使用派生类中同名方法,看上去派生类将基类的同名方法隐藏。只要函数名相同即可构成隐藏,与函数返回值和参数列表无关,如果一定要调用基类的方法,可以在方法前加类作用域,明确的告诉编译器我们要使用基类的方法,否则编译器默认使用派生类方法。
    class Base {
    public:
        Base(int data) :ma(data) { cout << "Base(int data)" << endl; }
        Base() = default;
        ~Base() { cout << "~Base()" << endl; }
    
        void show() { cout << "Base::show()" << endl; }
        void show(int val) { cout << "Base::show(int)" << endl; }
    
    protected:
        int ma;
    };
    
    class Deriver :public Base {
    public:
        Deriver(int data) :mb(data), Base(data) { cout << "Deriver(int data)" << endl; }
        ~Deriver() { cout << "~Deriver()" << endl; }
        
        void show(int a, int b, int c) { cout << "Deriver::show(int,int,int)" << endl; }
        int show(bool flg) { cout << "Deriver::show(bool)" << endl; return 0; }
    private:
        int mb;
    };
    
    int main() {
        Deriver d(100);
        //Deriver::show
        d.show(true);
        d.show(1,2,3);
    
        //Base::show
        d.Base::show();
        d.Base::show(99);
        return 0;
    }
    
  • 方法隐藏也是对于基类和派生类的同名方法而言的,包含两种情况:
    1. 基类方法是非虚方法的,派生类方法同名,基类成员函数被派生类成员函数隐藏:
      class A{
      	public:
      		void func1();
         }
      
      class B : public A{
      	public:
      		void func1(int); // hide A::func1()
      		virtual void func1(); // hide A::func1()
      }
      
      被隐藏的基类方法必须通过类作用域解析 A:: 才能被派生类对象调用:
      B b;
      b.func1(); // B::func1()
      b.A::func1(); // A::func1()
      b.func1(1) // B::func1(int)
      
    2. 基类和派生类方法都是虚函数,但同名不同参,基类被派生类方法隐藏:
      class A{
      	public:
      		virtual void func1();
        }
      
        class B : public A{
        	public:
        		virtual void func1(int); // hide A::func1()
        }
      
      如果直接通过对象调用类方法:
      B b;
      b.func1(); // error!
      b.func1(1); // B::func1(int)
      b.A::func1(); // A::func1()
      
      由于基类虚函数被隐藏,派生类对象 b 只能看到 B::func1(int) 方法,因此报 error: no matching function for call to function…
      如果通过基类指针或引用调用类方法:
      B b;
      A* pa = &b;
      pa->func1(); // ok
      pa->func1(1); // error!
      
      由于基类虚函数没有被重写而是被隐藏,基类指针或引用调用的类方法仍然是基类方法。
      如果基类与派生类出现同名数据成员,基类成员数据也会被隐藏,需要通过类名解析指定使用。总而言之,如果派生类需要使用被隐藏的基类成员,则必须通过 基类名:: 使得被隐藏的成员可见。

虚函数的重写与隐藏

  • 只有当基类与派生类的虚方法同名同参时,才能被重写。如果基函数的虚方法被隐藏,显然无法实现多态性。 因此,派生类重写基类虚函数应当遵循以下要求:
    • 派生类虚函数原型与基类虚函数完全相同,包括返回类型。(除返回类型协变外)
    • 如果基类虚函数被重载,则派生类虚函数也应当被重载。(如果只重写一个虚函数,则其它被重载的基类虚函数将被隐藏)
  • 重载函数重写示例:
    class A{
    	public:
    		virtual void func();
    		virtual void func(int); // overload
    		virtual void func(double, double); // overload
    }
    
    class B : public A{
    	public:
    		virtual void func(); // override
    		virtual void func(int); // override
    		virtual void func(double, double) // override
    }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咕噜咕噜的喵喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值