C++ 当您声明一个朋友,然后在类中定义它时,这意味着什么?
我试图理解一段代码片段,我通过反复试验成功地使其工作。我理解这个代码段的所有内容,除了当我从类声明中去掉“friend”时为什么它不起作用。我不明白朋友在这种情况下在做什么C++ 当您声明一个朋友,然后在类中定义它时,这意味着什么?,c++,C++,我试图理解一段代码片段,我通过反复试验成功地使其工作。我理解这个代码段的所有内容,除了当我从类声明中去掉“friend”时为什么它不起作用。我不明白朋友在这种情况下在做什么 细流测井 类日志包装器{ friend ostream&operator这意味着该朋友不是该类的成员,但您可以访问静态类成员和成员类型(包括私有成员) 这使得函数“外观和感觉”像一个成员。因为操作符通常友元只是告诉编译器,操作符您同时声明和定义友元函数,这会重载操作符 声明为friend的函数可以访问与它们成为好友的类的任
细流测井
类日志包装器{
friend ostream&operator这意味着该朋友不是该类的成员,但您可以访问静态
类成员和成员类型(包括私有
成员)
这使得函数“外观和感觉”像一个成员。因为操作符通常友元只是告诉编译器,操作符您同时声明和定义友元函数,这会重载操作符
声明为friend
的函数可以访问与它们成为好友的类的任何实例的所有私有成员
这与常规成员函数(显然也可以访问私有成员)不同,因为友元函数不是类的成员——它们是独立函数
因此,由于您已经在类中定义了独立函数,乍一看似乎很混乱——请记住,它根本不是一个真正的成员函数。除了之前编写的之外,查找规则略有不同。如果在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
}
[*]由于foo
是在B
的大括号内定义的,因此除非参数(至少一个参数)的类型为B
,否则查找将不会找到foo
,这将禁止从A
到B
的隐式转换,因为找不到潜在的重载,因此不会执行转换
这就是为什么在定义模板时,最好提供friend
函数(特别是运算符)的实现的原因之一内联,因为这减少了函数的范围并减少了命名空间污染。这意味着你的懒惰。但是懒惰在编程方面很好。@Martin:不仅仅是懒惰……它还有它的优点too@David罗德里格斯:是的,这就是为什么我说懒惰是好的。它隐式地记录了接口的紧密耦合和扩展。@Martin,它不仅隐式文档,但更改查找规则。如果在类括号内定义了友元
,则除非其中一个参数为封闭类类型,否则它在封闭命名空间中将不可用。@David:这一点很好。但请注意,99.9%的时间是正确的,因为友元的目的是为它提供访问成员。因此,除非您仅访问静态成员,否则其中一个参数将是封闭的对象。因此Koenig(或AD)lookup将用于查找函数。因此,您的语句在技术上是正确的,很少是factor。很抱歉,这基本上是错误的。Friend与Static无关,您可以通过对象访问普通成员(在本例中,第二个参数是thislogend
)@Cameron:friend
与static
无关,但在类{}
范围内定义意味着在类{}内定义的其他名称
scope不需要限定。这包括static
成员和成员类型。@马丁:我从来没说过你不能访问普通成员。哈?@David:这不是“类的一部分”;这就是重点。它不是一个成员函数,但为了方便/懒惰,它在类定义中被定义为友元函数定义的一部分。是的,除了:(a)它与函数定义中的w.r.t.限定规则略有不同;和(b)您忘记了类定义示例中的friend
语句。因此,如果我将一个函数声明为类内的friend,然后定义它,它将被定义为一个全局函数?那么,结果就是更漂亮的代码了?@Tomalak:我没有,OP甚至没有使用任何变量(如果它有变量的话)对于logWrapper
。这对于问题中提出的OP用例是特别的。@David Hinkle:您混淆了“自由函数”和“全局函数”这两个术语,但是你头脑中的想法基本上是正确的,是的。@Xeo:friend
是这个问题的关键。如果你要展示一个例子,说明friended函数的定义是不恰当的,我认为一个好的例子应该展示类定义中留下的friend函数声明。否则,它们就是甚至不接近于同等水平。
class logWrapper{
}logend;
ostream& operator<<(ostream& os, logWrapper& thislogend){
// ...
}
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);
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
}