把非成员函数放在类中是一种好的做法吗
Is it a good practise to put non member function inside a class?
我正在读这样的代码:
class Member
{
public:
friend std::istream& operator>>(std::istream& in, Member& m)
{
in >> m.name >> m.bYear >> m.bMonth;
return in;
}
friend std::ostream& operator<<(std::ostream& out,const Member& m)
{
out << m.name << " " << m.bYear << "." << m.bMonth;
return out;
}
private:
std::string name;
int year;
int month;
};
我以前从未见过这种情况。用friend
在类主体内定义非成员函数是一种好的做法吗?有什么优点和缺点吗?
和friend一起在类主体中定义非成员函数是一种好的做法吗?
我想说,这是一种冷漠的做法。
有什么优点和缺点吗?
优点
-
运算符可以引用类作用域中的类成员(嵌套类、typedef、枚举、常量、静态函数等),而无需显式地在它们前面加上类名
-
隐式地拥有流式传输函数
inline
是很方便的——没有一个定义规则会困扰 -
友谊意味着您可以方便地访问所有非公开会员
-
研究类源代码的人更有可能注意到的流功能
-
正如Mike Seymour所评论的,如果类是一个模板,那么定义一个朋友可以省略
template <
。。。运算符的>
方面,并将实例参数简单地称为const Member&
而不是const Member<
。。。>&
。
Cons
-
您可能想要一个越界的函数定义,这样您以后就可以修改实现,只需要重新链接(而不是重新编译)客户端代码
-
你给予的友谊可能在功能上是不必要的,这减少了封装,从而减少了的可维护性
-
寻找非会员流媒体运营商的人可能不会考虑查看类代码
-
你可能会认为它"扰乱"了类定义源代码,使其更难接受的所有实际类成员
与往常一样,接口和实现的干净分离的好处——既有利于管理物理依赖性(需要重新编译而不仅仅是重新链接),也有利于人类可读性——对于不同的高级库和应用程序使用的低级库来说,这一好处往往会增加,并且对于本地实现的"私有"支持要低得多(例如,.cpp
文件中匿名命名空间中的类,仅由该单个翻译单元使用,或者更确切地说,是private
嵌套类)。
一般来说,这不是的好做法;理想情况下实现甚至不会与类在同一个文件中释义(理想情况下,我们也不必声明头文件中的私有部分。)有很多但有正当理由的例外情况:
-
最明显的是在非常简单的助手类中真的没有足够的理由将两部分分开。如果辅助类是本地定义的,在源文件中,而不是在标头中。
-
另一种情况是针对朋友,尤其是在模板中。如果我写(甚至在模板中)
friend void f( MyClass& )
,然后我已经声明了一个非模板作为朋友,我必须为每个实现一个单独的非模板函数实例化类型。如果我在中提供内联实现然而,类定义,编译器将自动为每种类型创建单独的非模板函数习惯于这是一个非常频繁的定义动机类中的operator>>
和operator<<
,因为它们不能成员;通常它们将被声明为friend
,即使它们不需要访问私人成员,这样他们就可以这样定义。
最后,如果函数或运算符,它们仅在类中或ADL中可见。这应该不是问题,只要函数在至少一个涉及类的参数。
可能的Pro:如果在类主体中也定义了所有或大多数其他函数来处理类的私有成员,则更易于阅读和维护。它使事物保持在一起。
Con:类主体中定义的函数出现在每个编译单元中,而不是只编译一个相应的.cpp文件。
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- C++ STD 函数运算符:有没有一种方法可以通过函数将一个向量映射到另一个向量上?
- 如果 C 函数仍然可以间接执行(通过回调函数),那么将它声明为静态函数是否是一种不好的做法?
- 构造函数是否有一种现代C++方法来了解其'container'类?
- 有没有一种简单的方法可以在对象向量上调用构造函数?
- 有没有一种简单的方法来调用带有默认参数的函数?
- 有没有一种方法可以从函数中返回一个新对象或对现有对象的引用
- 在C++中,有没有一种方法可以让我在不传递参数的情况下拥有一个函数
- 有没有一种方法可以在linux中扫描已构建的ARM库中的函数
- 有没有一种方法可以获得传递给函数的数组的大小
- 常量静态成员函数:有另一种方法可用吗?
- C++11 中的随机数:有没有一种简单的方法可以将生成器种子放在代码的一个位置,然后在不同的函数中使用它?
- 是否有一种方法可以调用一个函数,而不会创建变量,而不会创建变量
- 有没有一种单行方法来调用集合上的 lambda 函数
- 是否有一种非间接、非黑客的方式来保证 constexpr 函数仅在编译时可调用?
- 是否有一种方法可以在超载运算符函数中接触默认运算符函数
- 是否有一种方法可以避免标头文件中使用的constexpr函数输入全局范围,而无需额外的名称空间
- 是否可以将一种函数类型转换为另一种采用相同参数但返回类型不同的函数类型
- 是c++模板元编程的一种函数编程形式