[英]What does it mean when you declare a friend and then define it inside a class?
I'm trying to understand a code snippet that I've managed to make work by trial and error. 我正在尝试理解我设法通过反复试验来完成工作的代码段。 I understand everything about this snippet except why it doesn't work when I take "friend" out of the class declaration.
我理解这个片段的一切,除了为什么当我把“朋友”带出课堂宣言时它不起作用。 I don't understand what friend is doing in this context.
在这种情况下,我不明白朋友在做什么。
stringstream log;
class logWrapper { friend ostream& operator<<(ostream& os, logWrapper& thislogend) { stringstream &ss = dynamic_cast(os); // This line replaced with printf for clarity // The actual code sends the C style string to a // legacy logging system that only takes C style strings // _log(LOG_ERR, "%s", ss.str().c_str()); printf("%s\n", ss.str().c_str());
ss.str("");
return os;
}
} logend;
int main(void)
{
log << "This is a test" << logend;
}
You are simultaneously declaring and defining a friend function, which overloads an operator. 您同时声明并定义了一个使运算符重载的友元函数。
Functions which are declared as friend
can access all the private members of any instance of the class which befriended them. 声明为
friend
函数可以访问与它们成为友好的类的任何实例的所有私有成员。
This is different from regular member functions (which can obviously also access private members), since friend functions are not members of the class -- they are stand-alone functions. 这与常规成员函数(显然也可以访问私有成员)不同,因为友元函数不是类的成员 - 它们是独立的函数。
So since you've defined the stand-alone function inside the class, it appears confusing at first glance -- just remember that it's not really a member function at all. 所以,既然你已经定义的类中的独立功能,乍看之下令人困惑-只记得它不是一个真正的成员函数都没有。
It means that the friend is not a member of the class, but you can access static
class members and member types (including private
ones) without qualification. 这意味着该朋友不是该类的成员,但您可以无限制地访问
static
类成员和成员类型(包括private
类)。
This makes the function "look and feel" like a member. 这使得“外观和感觉”功能成为一个成员。 Because
operator<<
here is intimately tied to the logWrapper
, it is intuitive that you can implement it as if it were a member of the class. 因为
operator<<
这里与logWrapper
密切相关,所以你可以直观地实现它,就像它是类的成员一样 。
But remember, it is not a member! 但请记住,它不是会员! It is just a free function with special access privileges, just as if it were defined outside.
它只是一个具有特殊访问权限的免费功能,就像在外部定义一样。
Edit: Since there are no static members and no member types, this happens not to make a difference here. 编辑:由于没有静态成员且没有成员类型,因此这不会产生任何影响。 You could move the definition of the friend outside without changing it.
你可以在不改变它的情况下将朋友的定义移到外面。 This style is idiomatic, though, because you could.
不过,这种风格是惯用的,因为你可以。 Often it is used with templates, which often do have member types/typedefs.
它通常与模板一起使用,模板通常具有成员类型/ typedef。
Indeed, defining a friend inside a template<…> class
block is the only way to define a templated non-template function . 实际上,在
template<…> class
块中定义朋友是定义模板化非模板函数的唯一方法。 This esoteric and sometimes-elusive beast is nonetheless sometimes very convenient to have around. 尽管如此,这种神秘的,有时难以捉摸的野兽有时也非常方便。 Usually his creation is accidental, even serendipitous, so I won't get into that discussion…
通常他的创作是偶然的,甚至是偶然的,所以我不会参与讨论......
Besides what has been written before, the lookup rules are slightly different. 除了以前写过的内容之外,查找规则略有不同。 If the
friend
function is declared and defined inside the befriending type, then it will only be considered if one of the arguments is of that particular type: 如果在befriending类型中声明和定义了
friend
函数,那么只会考虑其中一个参数是否属于该特定类型:
struct A {};
struct B {
B() {} // allow default construction
B( A const & ) {} // and implicit conversion from A
friend void foo( B const & ) // defined in the class
{}
friend void bar( B const & );
};
void bar( B const & ) {} // defined outside
int main() {
A a;
bar( a ); // ok, implicit conversion and calls bar(B(a))
//foo( a ); // error: foo not in scope!!! [*]
B b;
foo( b ); // ok: the argument makes the compiler look inside B
foo( B(a) ); // same here
}
[*] Since foo
is defined inside B
's braces, lookup will not find foo
unless the argument (at least one argument) is of type B
, and that will inhibit the implicit conversion from A
to B
--since the potential overload is not found, conversion is not performed. [*]因为
foo
是在B
的括号内定义的,所以查找将找不到foo
除非参数(至少一个参数)是B
,并且这将禁止从A
到B
的隐式转换A
因为潜在的重载是未找到,不执行转换。
This is one of the reasons why, when defining a template, it is better to provide the implementation of the friend
functions (specially operators) inline, as that reduces the scope of the functions and reduces namespace pollution. 这就是为什么在定义模板时,最好是内联地提供
friend
函数(特别是运算符)的实现,因为这会减少函数的范围并减少命名空间污染。
Normally friend
just tells the compiler, that the operator<<
has access to the private variables of logWrapper
. 通常
friend
告诉编译器, operator<<
可以访问logWrapper
的私有变量。 In your case it's used to directly implement the operator<<
inside the logWrapper
. 在你的情况下,它用于在
logWrapper
直接实现operator<<
。 Could've also been implemented like this: 也可以像这样实现:
class logWrapper{
}logend;
ostream& operator<<(ostream& os, logWrapper& thislogend){
// ...
}
If you didn't use friend
, you would declare that operator<<
as a member function of logWrapper
. 如果你没有使用
friend
,你会声明该operator<<
作为logWrapper
的成员函数。 It's easier to understand with a normal function: 使用普通函数更容易理解:
class logWrapper{
int func(int i, logWrapper& thislogend){
// ...
}
}logend;
// needs to be called as:
logend.func(5,logend);
// while
class logWrapper{
friend int func(int i, logWrapper& thislogend){
// ...
}
}logend;
// would be called as
func(5,logend);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.