【问题标题】:C++ : What is happening when a non-overridden calls a overridden method?C++:当非重写调用重写方法时会发生什么?
【发布时间】:2016-01-24 21:03:24
【问题描述】:

被调用的重写方法的版本取决于 如果您关心“通过”基类或“通过”派生类调用函数。但是,我发现如果我调用了一个非覆盖的方法,并且被覆盖的方法调用了一些 被覆盖的函数,那么即使我通过指针访问实例,仍会调用基类版本到派生类。有人可以解释为什么会这样吗?

代码:

class Base {
public:
    void display() {
        foo();
    }
    void foo() {
        cout << "Base.foo()" << endl;
    }
};

class Derived : public Base {
public:
    void foo() {
        cout << "Derived.foo()" << endl;
    }
};

int main() {
    Derived* derived = new Derived();
    derived->display();
    while (true) {}
}

【问题讨论】:

  • 你没有覆盖这些函数,因为它们不是virtual

标签: c++ overriding member-hiding


【解决方案1】:

基类版本仍然被调用,即使我正在访问 通过指向派生类的指针来实例化。有人可以解释一下 为什么会这样?

虽然你通过派生类的指针调用方法,但你的方法不是虚拟的,所以使用静态调度,所以Base::display()直接调用Base::foo(),即使它在子类中被覆盖。为了实现你想要的行为,你必须使用动态调度,即将你的方法标记为virtual

class Base {
public:
    void display() {
        foo();
        bar();
    }
    void foo() {
        cout << "Base.foo()" << endl;
    }
    virtual void bar() {
        cout << "Base.bar()" << endl;
    }
};

class Derived : public Base {
public:
    void foo() {
        cout << "Derived.foo()" << endl;
    }
    virtual void bar() {
        cout << "Derived.bar()" << endl;
    }
};

int main() {
    Derived* derived = new Derived();
    derived->display();
}

输出:

Base.foo()
Derived.bar()

【讨论】:

    【解决方案2】:

    问题是:你没有重写任何函数;你有hidden its name

    在 C++ 中,只有虚函数(参见 C++ FAQ)可以被覆盖。将 Base::foo() 设为虚拟会产生预期的结果:(run code!)

    class Base {
    public:
        void display() {
            foo();
        }
        virtual void foo() {
            cout << "Base.foo()" << endl;
        }
    };
    
    class Derived : public Base {
    public:
        void foo() {
            cout << "Derived.foo()" << endl;
        }
    };
    
    int main() {
        Derived* derived = new Derived();
        derived->display();
    }
    

    【讨论】:

      【解决方案3】:
      virtual qualifier needs to be used for methods that need to be overridden.
      ex:
       class Base {
      public:
          void display() {
              foo();
          }
          virtual void foo() {
              cout << "Base.foo()" << endl;
          }
      };
      
      class Derived : public Base {
      public:
          virtual void foo() {
              cout << "Derived.foo()" << endl;
          }
      };
      
      int main() {
          Derived* derived = new Derived();
          derived->display();
          while (true) {}
      }
      

      【讨论】:

        【解决方案4】:

        您没有使用虚函数。

        类层次结构中的对象有两种类型:它是“真正的”类,以及编译器当前认为它具有的类。

        当你调用一个虚函数时,编译器总是调用属于“真实”类的函数。当你调用一个非虚函数时,编译器调用的函数属于它认为是对象类的类。

        在子类中执行代码时,编译器认为 *this 是子类的对象。因此,调用非虚拟函数将调用属于该子类的函数。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-06-09
          • 1970-01-01
          • 2019-02-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多