如何在C++类B中调用被成员函数隐藏的类A友元函数foo?
在不重命名成员函数的情况下调用被隐藏的友元函数
先看你的问题代码:
struct A { friend void foo(A& a) {} }; struct B { void foo() { A a; foo(a); // 编译失败,B::foo 隐藏了全局友元函数 } }; int main() { A a; foo(a); // 正常调用,靠参数依赖查找找到A的友元foo }
你尝试的::foo(a)和A::foo(a)失败的原因:
A::foo(a)不行:友元函数不属于类A的成员,只是获得了访问A私有成员的权限,不能通过类名来调用。::foo(a)不行:虽然友元函数定义在全局作用域,但它是隐式声明的——在类内部定义友元函数时,除非外部有对应的声明,否则全局作用域中不会有这个函数的可见声明,编译器找不到它。
下面是两种可行的解决方法:
方法1:在类A外部声明全局foo函数
在类A的定义前后,声明全局的void foo(A&);,让全局作用域有这个函数的可见声明,之后就能用::foo(a)调用:
struct A; void foo(A&); // 全局声明foo struct A { friend void foo(A& a) {} // 和外部声明匹配的定义 }; struct B { void foo() { A a; ::foo(a); // 现在能找到全局的友元foo了 } }; int main() { A a; foo(a); // 依然正常工作 }
方法2:在B::foo内部用using引入全局foo
如果不想额外加全局声明,可以在B的成员函数里用using ::foo;引入全局域的foo名字,解除成员函数的隐藏:
struct A { friend void foo(A& a) {} }; struct B { void foo() { using ::foo; // 引入全局foo,覆盖成员函数的隐藏 A a; foo(a); // 现在调用的是全局友元foo } }; int main() { A a; foo(a); // 正常工作 }
补充说明
main函数里能直接调用foo(a),是因为参数依赖查找(ADL):当调用函数时,若参数是某个类的对象/引用,编译器会去该类的作用域查找匹配函数——这里参数是A&,所以编译器会到A的作用域找foo,而A的友元foo正好在那里可见,因此成功调用。但在B::foo里,成员函数foo会隐藏全局名字,编译器优先匹配当前作用域的函数,所以ADL不会触发,必须显式引入全局foo的名字,或者让全局foo有可见声明。
内容的提问来源于stack exchange,提问作者prapin
相关产品推荐
相关产品推荐

