C++成员函数虚拟覆盖和重载同时进行

bom*_*ier 29 c++ polymorphism virtual inheritance

如果我有这样的代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

我收到一个错误,指出我正在尝试从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;
}
Run Code Online (Sandbox Code Playgroud)

jal*_*alf 43

简短的回答是"因为这就是重载解析在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
};
Run Code Online (Sandbox Code Playgroud)

  • 可能想要添加一个关于函数隐藏的C++ FAQ的链接:http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9 (3认同)
  • @null:受损的名字并不重要.只有链接器才会看到错位的名称.但链接器不执行重载解析.这是由编译器完成的,它看到了原始的,未经修改的名称. (2认同)