我的第一篇文章所以请你放轻松!
我知道C++中的结构和类之间没有真正的区别,但包括我在内的很多人使用结构或类来显示意图 - 用于分组"普通旧数据"的结构和用于具有有意义操作的封装数据的类.
现在,这很好但是你在什么时候开始认为某些东西不仅仅是一个结构而且应该成为一个类?
我认为结构有合理的事情:
构造函数只有简单的初始化代码.
序列化代码,例如流插入/提取运算符.
我不太确定的事情,但可能会这样做:
比较运算符
简单的转换函数 - 例如,在从外部源接收数据后,以字节为单位等待所有成员.
我不认为结构应该有:
动态内存分配.
析构函数.
复杂的成员函数.
边界在哪里?
另外,将类实例作为结构的成员是否合理?例如
class C {private: int hiddenData; public: void DoSomething();}; struct S {int a; float b; C c; }; S s; s.c.DoSomething();
记住,我不是关于你可以用C++做什么,我对你在设计好的软件时应该做些什么感兴趣.
思考?
我认为有三个主要的,连贯的思想流派:
不关心任何方式,使用struct
和class
互换的人.
使用struct
s的人只代表小POD.
使用struct
s作为记录的人.
对于这些策略中的任何一个,我都无法做出决定性的论据.我倾向于遵循路径2,但是当我看到它适合时,我也使用非POD类型的结构,特别是对于功能对象(即使这些可能不符合POD要求).
(顺便提一下,C++ FAQ lite对POD有一个非常好的定义).
编辑我没有触及模板元编程技术,例如struct
用于占位符(类型标记)或实现元函数.我想在这些情况下绝对没有争议:因为它们从不包含方法(甚至数据),所以总是使用struct
).
我个人的偏好是只使用结构,如果根本没有方法的话.如果我因任何原因需要添加方法,那就是一个类.
类与结构
使用class或struct关键字是一种品味问题以及它在读者身上产生的" 感觉 ".从技术上讲,它们是等价的,但如果结构用于POD和C结构类型,则可读性更好.
应该放在C++结构中的基本内容:初始化数据的构造函数(我不喜欢使用memset,如果POD演变成不同的东西,它可以稍后回来)或者来自其他类型但不是复制构造函数的构造.
如果需要定义复制构造函数或赋值运算符,因为生成的编译器不够好,请将其设为类.
对于将被传递给STL算法和模板元编程的仿函数,通常使用结构,如
struct square_int { int operator()( int value ) { return value*value; } }; std::transform( v.begin(), v.end(), v.begin(), square_int() );
要么
// off the top of my head templatestruct is_pointer { enum { value = false } }; template struct is_pointer { enum { value = true } };
成员方法与自由功能
除了我之前所说的,这不会增加其他人已经回答的内容,我想把重点放在你在帖子中评论的其他类型的函数,作为比较运算符等.
无论是将它声明为类还是结构,通常更好地将对称(比较,算术),插入和删除运算符和转换的运算符实现为自由函数.
如果将对称运算符(与数据类型相关)实现为成员函数,则它们不是对称的.查找规则不会强制左侧调用成员函数,但它将应用相同的强制转换以匹配自由函数.
// Example of symmetry with free functions where method would be asymmetric int main() { std::string( "Hello " ) + "world"; // compiles as free / member function "Hello " + std::string( "world" ); // compiles with free function, fails with member function definition of + }
在上面的代码中,如果operator +是std :: string的成员方法,编译器将无法编译,因为它无法将const char*literal强制转换为std :: string以使用成员方法.
流中的插入和提取必须始终作为自由函数实现,因为流始终是操作的左侧.
将转换保持为自由函数可以将两种不同的类型分离.如果A和A'可以相互转换并且您决定将变换实现为A的成员,则A必须知道A',并且A的所有使用将取决于A',无论您是否使用它.如果将转换定义为自由函数,则A在没有A'的情况下完成,并且两个类/结构之间的耦合将更小.转换到/来自网络,序列化和反序列化也是如此.当您在类/结构中实现它们时,您将强制所有用户了解这些转换.