derived class 中的 using-declaration 不隐藏从 base class 派生的相同函数
using-declaration in derived class does not hide same function derived from base class
看看下面的代码:
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;
}
根据我的理解,C
中的 B::f()
应该隐藏通过 using 声明带到 C
的 A::f()
;如果是这样,那为什么 c.C::f()
仍然调用 A::f()
?
如果c.C::f()
调用A::f()
,那应该意味着在C
的范围内,f()
应该总是引用A::f()
,这是使用声明的功能。那么为什么在 C::test()
中,对 f()
的调用仍然被评估为 B::f()
?
非常好的问题,一个复杂的名称查找案例。
基本上,当在 C
的范围内查找名称 f
时,由于使用-宣言。因此C::test()
中的所有调用c.f()
、c.C::f()
和f()
,都将名称f
解析为A::f
。
接下来是虚拟调度。如果一个虚函数被一个不合格的名字调用,动态调度就会发生并调用最终的重写器。这包括 c.f()
和 C::test()
中的 f()
调用,因为它们是不合格的。
调用 c.C::f()
使用 f
的限定名称,这会抑制动态调度,并直接调用名称解析到的函数。由于该函数是 A::f
(多亏了 using 声明),因此 A::f
被非虚拟地调用。相关规则如下(引用C++14终稿N4140,强调我的):
§10.3/15
Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism.
§5.2.2/1
... If the selected function is non-virtual, or if the
id-expression in the class member access expression is a qualified-id, that function is called. Otherwise, its
final overrider (10.3) in the dynamic type of the object expression is called; such a call is referred to as a
virtual function call.
看看下面的代码:
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;
}
根据我的理解,C
中的 B::f()
应该隐藏通过 using 声明带到 C
的 A::f()
;如果是这样,那为什么 c.C::f()
仍然调用 A::f()
?
如果c.C::f()
调用A::f()
,那应该意味着在C
的范围内,f()
应该总是引用A::f()
,这是使用声明的功能。那么为什么在 C::test()
中,对 f()
的调用仍然被评估为 B::f()
?
非常好的问题,一个复杂的名称查找案例。
基本上,当在 C
的范围内查找名称 f
时,由于使用-宣言。因此C::test()
中的所有调用c.f()
、c.C::f()
和f()
,都将名称f
解析为A::f
。
接下来是虚拟调度。如果一个虚函数被一个不合格的名字调用,动态调度就会发生并调用最终的重写器。这包括 c.f()
和 C::test()
中的 f()
调用,因为它们是不合格的。
调用 c.C::f()
使用 f
的限定名称,这会抑制动态调度,并直接调用名称解析到的函数。由于该函数是 A::f
(多亏了 using 声明),因此 A::f
被非虚拟地调用。相关规则如下(引用C++14终稿N4140,强调我的):
§10.3/15
Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism.
§5.2.2/1
... If the selected function is non-virtual, or if the id-expression in the class member access expression is a qualified-id, that function is called. Otherwise, its final overrider (10.3) in the dynamic type of the object expression is called; such a call is referred to as a virtual function call.