C++ 优缺点大型项目类内定义的内联无好友助手函数
我试图列出类外定义的助手无好友函数和类内定义的助手无好友函数之间的所有差异 我正在考虑遵循以下规则:在类的主体中声明所有helper函数为friend,但它并没有广泛传播,所以我想知道我是否没有遗漏一些缺点C++ 优缺点大型项目类内定义的内联无好友助手函数,c++,C++,我试图列出类外定义的助手无好友函数和类内定义的助手无好友函数之间的所有差异 我正在考虑遵循以下规则:在类的主体中声明所有helper函数为friend,但它并没有广泛传播,所以我想知道我是否没有遗漏一些缺点 让我们考虑一个包含几十个类的命名空间,这些范围都是范围,对于这个例子,我们将类代码>开始/代码>放在类的主体内,并在类的主体之外的代码>结束/代码>(很明显,目的是不评论这个不一致性) 优点: 如果用户状态开始(x)和x不实现begin程序编译器不会列出所有重载的begin,因为只有当x实
让我们考虑一个包含几十个类的命名空间,这些范围都是范围,对于这个例子,我们将类代码>开始/代码>放在类的主体内,并在类的主体之外的代码>结束/代码>(很明显,目的是不评论这个不一致性)
优点:- 如果用户状态
和x不实现开始(x)
程序编译器不会列出所有重载的begin,因为只有当x实际实现begin helper函数时,begin才可访问。(begin在命名空间作用域:[classes.friends]中不可见,N4659中的第7项,在类中定义的友元函数位于定义它的类的(词法)作用域中)。如果用户声明begin
并且在命名空间end(x)
中声明了x的类型,编译器将列出所有数十个nm
声明和潜在的重载end
- 无法通过用户定义的转换函数访问begin(),这可能是不需要的
- 如果用户状态
且x未实现begin(x)
,则不会通知用户命名空间的其他类实际存在begin
begin
- begin()无法通过用户定义的转换函数进行访问,这可能是需要的
操作符==
?那么“类中定义的友元函数在其定义的类的(词法)范围内”意味着在A的主体中声明的任何友元函数都属于A的命名空间(A的词法范围)
换言之:
namespace ns {
class A
{
static int bar()
{
return 21;
}
public:
inline friend int foo(A& a)
{
return A::bar();
}
friend int foo2(A& a);
};
} // namespace ns
int foo2(ns::A& a) // this will fail, since only ns::foo2() is friend of A
{
return foo(a);
}
namespace ns {
int foo2(ns::A& a) // this works
{
return foo(a);
}
} // namespace ns
int main(int, const char**, const char**)
{
ns::A var;
return ns::foo(var) + ns::foo2(var);
}
指出begin()在命名空间范围内不可见是错误的。begin()和end()的可见性相同。记住朋友函数不是成员函数,所以它可能不是正确的词。我将在标准中看到什么。@米莎席罗伊C++标准(N4665)[类朋友]项目7在一个类中定义的朋友函数位于定义的类的(词法)范围内,作用域是相同的。友元函数具有全局作用域,不属于它们的友元结构。。。你把尸体放在哪里并不重要。。。例如:一个函数可以是许多类的朋友,但只能有一个主体。然而,我们知道在您的示例中,您不能将begin()称为nm::a::begin(const a&)。它的名字是nm::begin(const A&),这应该会给你一个关于它的词汇层次结构的强烈提示。你确实缺少了一些东西。你不能回答这个问题。您要解释的是,ADL(参数相关查找)也称为Koening查找,它只查找在参数类型的直接封闭命名空间内声明的名称。到目前为止,这么好,这是C++基础知识吗?我所说的是这样一个事实:如果友元函数是在类主体内部定义的,并且如果它没有在类外部进一步声明,那么它在名称空间范围内是不可见的。。。仔细看这里的错误消息,我一直在使用friend函数,从来没有出现过这个问题。在上面的示例中,
foo()
在ns
和全局名称空间中可见。这是因为您总是在类之外声明或定义友元函数。这不是一个问题,标准中有意说明这一点,以某种方式限制ADL。我的问题是,这是否是一种好的做法。我这么认为是因为它避免了不必要的转换。。。但我仍然有疑问。
namespace ns {
class A
{
static int bar()
{
return 21;
}
public:
inline friend int foo(A& a)
{
return A::bar();
}
friend int foo2(A& a);
};
} // namespace ns
int foo2(ns::A& a) // this will fail, since only ns::foo2() is friend of A
{
return foo(a);
}
namespace ns {
int foo2(ns::A& a) // this works
{
return foo(a);
}
} // namespace ns
int main(int, const char**, const char**)
{
ns::A var;
return ns::foo(var) + ns::foo2(var);
}