Почему статический метод переопределяет нестатический метод базового класса?

struct B {
  void foo () {}
};

struct D : B {
  using B::foo;
  static void foo () {}
};

int main ()
{
  D obj;
  obj.foo();  // calls D::foo() !?
}

Метод Member и метод члена static полностью различаются по двум причинам:

  • static не отменяет виртуальные функции в базе class
  • подпись указателя функции для обоих случаи разные

Когда метод вызывается объектом, не должен ли метод-член иметь более высокое предпочтение логически? (Только то, что С++ позволяет вызывать метод static с помощью объекта, будет ли он рассматриваться как переопределенный метод?)

Ответ 1

Правило, которое вы видите, описано в ISO/IEC 14882: 2003 7.3.3 [namespace.udecl]/12:

Когда декларация использования приносит имена из базового класса в область производного класса, функции-члены в производном классе переопределяют и/или скрывают функции-члены с тем же именем и типами параметров в базовом классе (а не в конфликте).

Без этого правила вызов функции будет неоднозначным.

Ответ 2

Проблема здесь в том, что вы не можете перегружать статический метод, используя нестатический метод с той же сигнатурой.

Теперь, если вы попробуете:

struct D {
  void foo () {}
  static void foo () {}
};

Это приведет к ошибке.

Я не уверен, почему в случае using B::foo он фактически игнорируется без предупреждения об ошибке/предупреждении (по крайней мере, в GCC 4.5.1).