请看以下代码:
struct A {
public:
virtual void f(){std::cout << "in A";};
};
struct B : A{
public:
virtual void f(){std::cout << "in B";};
int a;
};
struct C : B{
using A::f;
void test(){f();}
};
int main()
{
C c;
c.f(); // calls B::f, the final overrider
c.C::f(); // calls A::f because of the using-declaration
c.test(); //calls B::f
return 0;
}根据我的理解,B::f() in C应该隐藏通过使用-声明而带到C的A::f();如果是这样的话,为什么c.C::f()仍然调用A::f()?
如果c.C::f()调用A::f(),这意味着在C的范围内,f()应该总是引用A::f(),这是using-声明的函数。那么为什么在C::test()中,对f()的调用仍然被计算为B::f()
发布于 2015-02-11 08:14:53
很好的问题,一个复杂的名字查找案例。
基本上,当在f的作用域中查找名称C时,由于使用声明,它总是会找到A::f。因此,所有调用c.f()、c.C::f()和f()的C::test(),将名称f解析为A::f。
接下来是虚拟调度。如果以不限定的名称调用虚拟函数,则会发生动态调度,并调用最终的覆盖器。这包括c.f()和C::test()中的f()调用,因为它们是不合格的。
调用c.C::f()使用f的限定名,这将抑制动态调度,并直接调用名称解析的函数。由于该函数是A::f (由于使用-声明),所以A::f被称为非虚拟函数。有关规则如下(引用C++14最后草案N4140,重点是地雷):
§10.3/15
使用作用域运算符(5.1)的显式限定将取消虚拟调用机制。
§5.2.2/1
..。如果所选函数为非虚拟函数,则为,或者如果类成员访问表达式中的是限定-id,则调用该函数。否则,调用对象表达式的动态类型中的最终覆盖器(10.3);这样的调用称为虚拟函数调用。
https://stackoverflow.com/questions/28449304
复制相似问题