Liu*_*ick 25 c++ using-declaration
看看下面的代码:
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应该隐藏使用声明A::f()带来的内容C; 如果是的话,为什么c.C::f()还要打电话A::f()?
如果c.C::f()调用A::f(),这应该意味着,在范围C,f()应始终参考A::f(),这是使用声明的功能.然后为什么在C::test(),呼叫f()仍然评估B::f()?
Rei*_*ica 29
非常好的问题,一个复杂的名称查找案例.
基本上,当f在范围内查找名称时C,它总是会A::f因使用声明而找到.因此,所有的通话c.f(),c.C::f()以及f()在C::test(),解析名称f来A::f.
接下来是虚拟调度.如果通过非限定名称调用虚函数,则会发生动态调度并调用最终的覆盖.这涵盖c.f()和f()呼吁C::test(),因为这些是不合格的.
该调用c.C::f()使用限定名称f,该名称禁止动态调度以及直接调用名称解析的函数.由于该功能A::f(由于使用声明),因此A::f被称为非虚拟的.相关规则如下(引用C++ 14最终草案N4140,强调我的):
10.3节/ 15
使用范围运算符(5.1)进行显式限定可以抑制虚拟调用机制.
§5.2.2/ 1
...如果所选函数是非虚拟的,或者类成员访问表达式中的 id- expression是qualified-id,则调用该函数.否则,调用对象表达式的动态类型中的最终覆盖(10.3); 这种调用称为 虚函数调用.