跳至主要內容

重载,隐藏,重写(覆盖)

张威大约 4 分钟c/c++继承

重载,隐藏,重写(覆盖)

(1)重载(overload)

[函数重载 | 张威的编程学习笔记 (gitee.io)](https://iszhwei.gitee.io/ccpp/02 c__基础/函数重载.html)

  1. 同⼀作用域当中的同名成员函数才存在重载关系
  2. 函数名相同参数列表不同(类型、数目、顺序)
  3. 返回值不同不能区分函数
class A{
    ...
    virtual int fun();
    void fun(int);
    void fun(double, double);
    static int fun(char);
    ...
}

重写(覆盖)(override)

  1. 重写指的是在派⽣类中覆盖基类中的同名函数,重写就是重写函数体
  2. 要求基类函数****
  3. 参数列表返回值与基类虚函数相同
//⽗类
class A{
public:
    virtual int fun(int a){}
}
//⼦类
class B : public A{
public:
    //重写,⼀般加override可以确保是重写⽗类的函数
    virtual int fun(int a) override{}
}

重载与重写的区别:

  1. 重写是⽗类和⼦类之间的垂直关系;重载是不同函数之间的⽔平关系
  2. 重写要求参数列表和返回值相同;重载则要求参数列表不同,返回值不要求
  3. 重写关系中,调⽤⽅法根据决定;重载根据调⽤来选择函数体

(3)隐藏(hide)

隐藏:某些情况下,派⽣类中的函数屏蔽了基类中的

隐藏是指的把**作用域隐藏**了,因此可以加作用域进行访问;优先找的是派生类自己作用域的成员,没有才去基类里面去找

  1. 两个函数参数,但是****。

    • 和重写的区别在于
    //⽗类
    class A{
    public:
        void fun(int a){
        cout << "A中的fun函数" << endl;
      }
    };
    
    //⼦类
    class B : public A{
    public:
        //两个函数参数相同,但是基类函数不是虚函数。
        //隐藏⽗类的fun函数
        void fun(int a){
        cout << "B中的fun函数" << endl;
      }
    };
    int main(){
        B b;
        b.fun(2); //调⽤的是B中的fun函数
        b.A::fun(2); //调⽤A中fun函数
        return 0;
    }
    
  2. 两个函数参数

    • 和重载的区别在于
    //⽗类
    class A{
    public:
        virtual void fun(int a){
        cout << "A中的fun函数" << endl;
      }
    };
    //⼦类
    class B : public A{
    public:
        //两个函数参数不同,⽆论基类函数是不是虚函数,都会被隐藏。
        //隐藏⽗类的fun函数
       virtual void fun(char* a){
         cout << "A中的fun函数" << endl;
       }
    };
    int main(){
        B b;
        b.fun(2); //报错,调⽤的是B中的fun函数,参数类型不对
        b.A::fun(2); //调⽤A中fun函数
        return 0;
    }
    
    • b.A::fun(2); //调⽤A中fun函数
    // ⽗类
    class A {
    public:
        virtual void fun(int a) { // 虚函数
            cout << "This is A fun " << a << endl;
        }  
        void add(int a, int b) {
            cout << "This is A add " << a + b << endl;
        }
    };
    // ⼦类
    class B: public A {
    public:
        void fun(int a) override {  // 覆盖
            cout << "this is B fun " << a << endl;
        }
        void add(int a) {   // 隐藏
            cout << "This is B add " << a + a << endl;
        }
    };
    int main() {
        // 基类指针指向派⽣类对象时,基类指针可以直接调用到派⽣类的覆盖函数,也可以通过 :: 调⽤到基类被覆盖
        // 的虚函数;⽽基类指针只能调⽤基类的被隐藏函数,⽆法识别派⽣类中的隐藏函数。
        A *p = new B();
        p->fun(1);      // 调⽤⼦类 fun 覆盖函数
        p->A::fun(1);   // 调⽤⽗类 fun
        p->add(1, 2);
        // p->add(1);      // 错误,识别的是 A 类中的 add 函数,参数不匹配
        // p->B::add(1);   // 错误,⽆法识别⼦类 add 函数
        return 0;
    }
    

    ,基类指针可以直接调用到派⽣类的,也可以通过 :: 调⽤到基类被覆盖的虚函数;⽽