为什么静态方法覆盖基类非静态方法?

11
struct B {
  void foo () {}
};

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

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

成员方法和static成员方法有两个完全不同的原因:

  1. static方法不会覆盖基本class中的虚函数
  2. 两种情况下的函数指针签名是不同的

当一个方法由对象调用时,逻辑上成员方法应该具有更高的优先级吗?(只是C++允许使用对象调用static方法, 这是否被认为是被覆盖的方法?)

2个回答

9
您正在看到的规则描述在ISO/IEC 14882:2003 7.3.3 [namespace.udecl] / 12中:
当“using-declaration”将名称从基类引入派生类范围时,派生类中的成员函数会覆盖和/或隐藏基类中具有相同名称和参数类型的成员函数(而不是冲突)。
没有这个规则,函数调用将会产生歧义。

静态成员也适用吗?如果是的话,为什么静态方法会与虚拟方法冲突? - iammilind
@iammilind 因为这仅适用于使用声明。 - Šimon Tóth
2
@iammilind:在这一点上,“virtual”和“static”没有任何区别,因为只是重载决议确定应该在您的“D”对象上调用哪个函数。 - CB Bailey
1
这里最不明显的是:在进行非静态解析时,没有理由考虑静态方法,但这只是事情运作的方式。 - Eamon Nerbonne
2
@Eamon:这完全取决于"脆弱"的基类。问题在于静态方法可能通过 dot 调用。从这一点开始,隐藏 是必须的,否则在基类中引入 foo 可能会破坏所有客户端代码。 - Matthieu M.

1

这里的问题是你不能使用与非静态方法相同签名的非静态方法重载静态方法。

现在,如果你尝试:

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

这将触发一个错误。

我不太确定为什么在使用B::foo的情况下,它实际上会在没有触发错误/警告的情况下被静默忽略(至少在GCC 4.5.1上)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接