【问题标题】:C++ member function virtual override and overload at the same timeC++成员函数虚覆盖和同时重载
【发布时间】:2010-10-09 19:29:24
【问题描述】:

如果我有这样的代码:

struct A {
  virtual void f(int) {}
  virtual void f(void*) {}
};

struct B : public A {
  void f(int) {}
};

struct C : public B {
  void f(void*) {}
};


int main() {
  C c;
  c.f(1);

  return 0;
}

我收到一条错误消息,提示我正在尝试进行从 int 到 void* 的无效转换。为什么编译器不能确定他必须调用 B::f,因为这两个函数都被声明为虚拟函数?


在阅读了 jalf 的答案后,我进一步减少了它。这个也不行。不是很直观。

struct A {
  virtual void f(int) {}
};

struct B : public A {
  void f(void*) {}
};


int main() {
  B b;
  b.f(1);

  return 0;
}

【问题讨论】:

    标签: c++ inheritance polymorphism virtual


    【解决方案1】:

    简短的回答是“因为这就是 C++ 中重载解析的工作方式”。

    编译器在 C 类中搜索函数 F,如果找到,它会停止搜索,并尝试从中挑选一个候选函数。如果在派生类中没有找到匹配的函数,它只会在基类内部查找。

    但是,您可以将基类函数显式引入派生类的命名空间:

    struct C : public B {
      void f(void*) {}
      using B::f; // Add B's f function to C's namespace, allowing it to participate in overload resolution
    };
    

    【讨论】:

    • 可能想要添加一个指向 C++FAQ 的函数隐藏链接:parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
    • @jalf:这种编译器行为的原因是什么?为什么不搜索基类以找到适合调用的函数?
    • 那个的原因是什么?编译器必须选择一些行为,这在某些情况下是有道理的,而在其他情况下似乎很荒谬。此方案的优点是您可以选择加入“继续搜索”行为。但如果那样的话,就没有办法选择退出它并获得 this 行为。最终,语言设计者不得不做出决定,他们选择了这种行为。 :)
    • @jalf,名称混乱,f(int) 和 f(void*) 会得到不同的名称,那么搜索 f(int) 如何以 f(void*) 结束?而且匹配函数签名而不是函数名也是有意义的。
    • @null: 名称混乱无关紧要。只有链接器才能看到错位的名称。但是链接器不做重载决议。这是由编译器完成的,它会看到原始的、未修改的名称。
    【解决方案2】:

    或者你可以这样做:

    void main()
    {
        A *a = new C();
        a->f(1);  //This will call f(int) from B(Polymorphism)
    }
    

    【讨论】:

      【解决方案3】:

      嗯,我想首先你不明白什么是虚拟机制或多态。仅通过使用对象指针来实现多态性时。我认为你是 C++ 的新手。如果不使用对象指针,则没有多态性或虚拟关键字使用基类指针并将所需的派生类对象分配给它的意义。那就打电话试试吧。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-22
        • 2015-06-17
        • 1970-01-01
        • 2011-03-31
        • 1970-01-01
        • 2020-08-21
        • 2014-07-23
        相关资源
        最近更新 更多