Joh*_*nes 10 c++ friend friend-function
最小的例子:
class A
{
friend void swap(A& first, A& second) {}
void swap(A& other) {}
void call_swap(A& other)
{
swap(*this, other);
}
};
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
g ++ 4.7说:
friend.cpp: In member function ‘void A::call_swap(A&)’:
friend.cpp:7:20: error: no matching function for call to ‘A::swap(A&, A&)’
friend.cpp:7:20: note: candidate is:
friend.cpp:4:7: note: void A::swap(A&)
friend.cpp:4:7: note: candidate expects 1 argument, 2 provided
Run Code Online (Sandbox Code Playgroud)
退出第4行:
// void swap(A& other) {}
Run Code Online (Sandbox Code Playgroud)
......它工作正常.如果我想保留交换功能的两种变体,为什么以及如何解决这个问题?
我相信这是因为编译器试图在类中找到该函数.这应该是一个简单的改变,使其工作(它在Visual Studio 2012中工作):
class A; // this and the next line are not needed in VS2012, but
void swap(A& first, A& second); // will make the code compile in g++ and clang++
class A
{
friend void swap(A& first, A& second) {}
void swap(A& other) {}
void call_swap(A& other)
{
::swap(*this, other); // note the scope operator
}
};
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
为什么
在类中,在类中作用域的名称隐藏了周围命名空间中的名称; 所以朋友(其名称在命名空间中作用域,但不能直接在那里访问)被成员隐藏(在类中作用域)并且在这里不可用作潜在的重载.(更新:或者它可能比这更复杂,如评论中所述.范围和名称查找规则有点难以理解,特别是当涉及到朋友时).
如果我想保留交换功能的两种变体,如何解决这个问题?
没有完美的解决方案.如果函数都做同样的事情,那么只需使用其他成员函数中的成员.如果你在类定义之外声明了朋友,那么它可以作为::swap; 但是如果将类放在不同的命名空间中,这有点脆弱.(更新:或使用此答案建议的静态成员函数;我没有想到这一点).
作为解决方法,您可以声明一个static版本swap.然后,您可以声明friend版本以调用static版本.
class A
{
public:
friend void swap(A& first, A& second) { A::swap(first, second); }
private:
static void swap(A& first, A& second) {}
void swap(A& other) {}
void call_swap(A& other)
{
swap(*this, other);
}
};
int main () {
A a, b;
swap(a, b);
}
Run Code Online (Sandbox Code Playgroud)