首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当你声明一个朋友,然后在一个类中定义它,这意味着什么?

当你声明一个朋友,然后在一个类中定义它,这意味着什么?
EN

Stack Overflow用户
提问于 2011-04-05 06:37:21
回答 4查看 2K关注 0票数 6

我正在尝试理解一段代码片段,这段代码片段是我通过反复试验成功的。我理解这段代码的所有内容,除了当我将"friend“从类声明中去掉时,它为什么不起作用。我不明白在这种情况下朋友在做什么。

代码语言:javascript
运行
复制
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;
}
EN

回答 4

Stack Overflow用户

发布于 2011-04-05 06:46:53

同时声明和定义一个友元函数,该函数重载了一个运算符。

声明为friend的函数可以访问与它们成为好友的类的任何实例的所有私有成员。

这与常规成员函数(显然也可以访问私有成员)不同,因为友元函数不是类的成员--它们是独立的函数。

因此,由于您已经在类中定义了独立函数,所以乍一看它似乎很混乱--只需记住它根本不是一个真正的成员函数。

票数 7
EN

Stack Overflow用户

发布于 2011-04-05 06:40:53

这意味着该朋友不是类的成员,但您可以访问static类成员和成员类型(包括private成员),而无需限定。

这使得函数“看起来和感觉”像是一个成员。因为这里的operator<<logWrapper紧密相关,所以您可以直观地将其作为类的成员进行实现。

但请记住,它不是成员!它只是一个具有特殊访问权限的自由函数,就好像它是在外部定义的。

编辑:由于没有静态成员,也没有成员类型,这在这里不会有什么区别。您可以将好友的定义移到外部,而不更改它。但是,这种风格是惯用的,因为您可以。它通常与模板一起使用,模板通常有成员类型/typedefs。

实际上,在template<…> class块中定义友元是定义模板化非模板函数的唯一方法。尽管如此,这种深奥而有时难以捉摸的野兽有时还是非常方便的。通常他的创作是偶然的,甚至是偶然的,所以我不会深入讨论…

票数 3
EN

Stack Overflow用户

发布于 2011-04-05 16:09:17

除了之前编写的内容之外,查找规则略有不同。如果friend函数是在befriending中声明和定义的,那么只有当其中一个参数属于该特定类型时,才会考虑该函数:

代码语言:javascript
运行
复制
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,这将禁止从AB的隐式转换--由于没有发现潜在的重载,因此不会执行转换。

这就是为什么在定义模板时,最好以内联方式提供friend函数(特别是运算符)的实现的原因之一,因为这样可以减少函数的范围并减少名称空间污染。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5545112

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档