Google C ++样式guide建议将结构用于被动对象而不是类。被动对象有哪些好的用例(带示例)? 对被动对象使用结构(而不是类)有什么好处?
答案 0 :(得分:2)
被动对象通常是不会与其他对象进行交互的对象。这方面的一个例子是一个点的数学表示:
struct Point
{
float x, float y;
}
点在技术上不会与其他对象交互,它是被动。
非被动对象将是一个使用其他对象执行任务的对象,尤其是对于函数。编写一个可以处理网络I / O的类应该是一个类,因为它将使用许多其他对象来处理套接字,地址等。我当前程序的一个简单示例:
就好处而言,拥有一个结构意味着您不需要为您的成员设置gettors / settors。除非明确定义,否则struct成员/方法是隐式public
。这意味着更少的代码,以及轻微的内存改进。如果对象没有函数,则不会创建函数表。没那么大,但仍然是一个进步。您也没有函数调用的开销。
类是相反的。它们是隐式的private
,只有在明确定义时才会公开。私有数据意味着您需要与所述数据交互的功能。这通常意味着将其隐藏在界面后面。这是我正在制作的IRC客户端的界面:
enum IRC_RESPONSE
{
RSP_IGNORE = 0,
RSP_CONTINUE,
RSP_RET_TRUE,
RSP_RET_FALSE,
RSP_BREAK
};
class IRC_Client
{
public:
//Initialize all sockets and stuff given IP, port, etc
bool Initialize(const char *address, const int port);
//login to server, give login info
bool Login(const char *password, const char *nickname, const char *user);
//disconnect
bool Disconnect();
//main update loop
void Run();
//join/leave channel
void Join(const std::string channel);
void Part(const std::string channel);
//main update
private:
// MEMBERS ////////////////////////////////////////////////////////
SOCKET ClientSocket_; //socket of the client
sockaddr_in *ServerAddress_; //address of the server
std::string Nickname_; //nickname of user
// METHODS ////////////////////////////////////////////////////////
//parsing user input to decide what to do
bool HandleUserInput(std::string message);
//handling any message from server
IRC_RESPONSE HandleServerMessage(std::string message);
//send message
void SendMessage(std::string message);
void SendMessage(std::string prefix, std::string command, std::string parameters, std::string trail);
// UTILITIES //////////////////////////////////////////////////////
//pull nickname from prefix
std::string GetNickname(std::string prefix);
//parse
void ParseServerMessage(std::string message, std::string &prefix, std::string &command, std::string &end, std::vector<std::string> ¶meters);
// USER INPUT /////////////////////////////////////////////////////
static void *_inputThread(void*);
};
这个课程根本不是被动的!我使用sockaddr_in
之类的结构。我也使用像std::string
这样的类。使这个类很好,因为我隐藏了用户的实现,以保持生活简单。
答案 1 :(得分:1)
被动对象有哪些好的用例(带示例)?
使用完全面向对象,封装的用户定义类型,只要面向客户端的API /功能得到尊重,开发人员就可以合理地期望能够自由添加,删除,重新排序或更改私有数据的类型。
有时候你不需要这样的封装,并且需要向开发人员强调这种自由不存在,而是在某种程度上“客户” - 无论是在同一个类的其他地方(对于嵌套类/结构)还是命名空间,实施文件,库,应用程序或IPC连接的“系统”是故意允许将自己耦合到选定的数据成员。
这可能是因为:
在读取或写入内存或流时,您需要一个与所需编码匹配的特定数据表示,因为与客户有关于该数据成员或布局的协议(例如ping协议,东京证券交易所箭头标准协议,MS Excel 7.0版文档标准,一个汇编语言例程,你将调用它需要一个指向特定数据的指针,一些通过“内存”读/写访问的硬件总线)“更大”(更稳定/更长寿,官方)比任何单一的数据处理实现:数据更改的可能性极小(或不可能 - 您不能追溯性地更改Excel版本使用的数据格式)和/或您准备好的基础让你的程序中断,并且必须重新访问数据的所有用途来修复它。
“客户端”使用的范围相对较小(例如,嵌套在另一个中的私有类/结构,或实现文件中的匿名命名空间中的一个),这样如果数据的返工有限则更改,并且网络代码编写/维护/可理解性受益于公共数据成员的简单性和简洁性,并避免访问说明符和简单的get / set函数。
一个例子:一个Weighted_Average
类,内部保存了许多样本的列表,其中包含捕获它们时的时间戳 - 它可能会合理地将数据类型的实例与timeval
一起混为一谈或std::chrono::time_point
到struct
,vector
可用于实例化list
或struct
。
对被动对象使用结构(而不是类)有什么好处?
具有最小的功能优势(唯一的语言区别在于对基础和成员的默认访问,这使得struct
更简洁,如果您想要这样的公开)。
Google风格指南的动机在其中清楚表达:
我们为每个关键字添加自己的语义含义
这只是说他们使用class
vs class
来编码某个类型是否是被动的(根据他们的定义)。
更一般地说,许多编码样式使用struct
vs struct
的选择来编码类型的封装级别的一些模糊相似的方面。就个人而言,Google指南未明确允许我使用Hash
的许多案例,例如:
从抽象观察者派生一个具体的观察者,同时覆盖各种事件的虚拟回调,其中观察者对其所使用的类是私有的
编写简单的无状态仿函数(例如Equal
,std::unordered_map
用于实例化struct Impl;
)或谓词
struct
此外,我根据我准备让客户拥有的依赖关系/耦合来决定,这与struct
是否会有更复杂的成员函数无关。我认为Google没有理由限制struct
成员函数,因为这些函数没有强制执行后置条件或不变量,因为数据成员可以直接访问这些条件或不变量。换句话说 - 只要函数调用后struct timeval { int64_t tv_sec, tv_usec; };
的数据良好,谁关心函数是否正常。举一个具体的例子,如果给normalise()
tv_usec
函数确保tv_sec
在[0..1,000,000]微秒范围内并且有时相应地调整{{1}},那么好的:它不会干扰数据的任何其他用途。