使用Set/Get-like方法或GetSet组合函数

Use of Set/Get-like Methods or a GetSet combo function

本文关键字:GetSet 组合 函数 方法 Set Get-like 使用      更新时间:2023-10-16

我喜欢在类中使用C#风格的GetsSets。然后我遇到了以下示例:注意Port类中第二个SetPort的声明,即

inline uint16_t & SetPort ( ) { return this->port; } 

通过使用"与"符号,您可以创建一个既可以用作Set又可以用作Get的函数,如示例代码所示。我的问题是,为什么要这样做,或者反过来说,为什么要?也许我应该叫它:

inline uint16_t & GetSetPort ( ) { return this->port; }

我理解,我想,为什么这样做有效,我只是想知道,除了减少获取/设置的数量之外,是否有人认为这样做有任何实用性?

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <string.h>
#include <netinet/in.h>
using namespace std;
class Port {
public:
Port ( ) { }
Port ( const Port& orig ) { }
virtual ~Port ( ) { }
inline const uint16_t   GetPort ( ) { return this->port; }
inline void             SetPort ( const uint16_t p_a ) { this->port = p_a; }
inline uint16_t &       SetPort ( ) { return this->port; }
protected:    
in_port_t port;
};
int main ( int argc, char** argv )
{
Port * p = new Port ( );
p->SetPort ( 32);
cout << " Port value = " << p->GetPort () << endl;
p->SetPort() = 64;
cout << " Port value = " << p->GetPort () << endl;
p->SetPort(p->SetPort() + 32);
cout << " Port value = " << p->GetPort () << endl;
delete p;
return 0;
}

结果

Port value = 32
Port value = 64
Port value = 96

您想问自己的问题是"我为什么要使用setter/getter?"。

原因通常是为了改进封装,以便能够更好地调试代码(您可以非常容易地记录所有集(。您还可以隐藏实现细节(可能有"getter",但它后面不必有任何一个字段(。

我的观点是,如果您试图在编写这些函数时节省击键次数,并且您愿意通过在外部返回对私有变量的可修改引用来打破封装,那么最好使用纯公共字段。然而,如果您能看到getter和setter在未来很有用,那么您一定应该小心地编写它们来封装您的代码。毕竟,它是您正在设计的类的API。

详细说明您返回引用的具体示例,以便用户可以以这种方式设置值。你有点违背了二传手的目的。

  • 您不能检查用户提供的值,例如记录一些特殊情况
  • 你甚至不知道用户什么时候设置值,因为他可以保存引用以备以后更改
  • 如果只有一个方法同时执行get和set,则会完全丢弃对象的常量(不能仅const实例中获取值(

在设计C++类时,我倾向于使用完整的get/set组合。当我处理的只是一个小数据持有者(通常只是一堆分组在一起的字段(时,我倾向于使用struct并将所有字段公开。

至于C#,在C#中,自动属性是一种很好的语法糖,它几乎不需要任何成本,而且在需要时编写和重写都很简单。但是,请记住,这些不会破坏封装。

如果您有特定范围的可接受值,您仍然可以使用get-set组合函数,而不会危及封装:

#include <limits.h> // For UINT_MAX
class CPort {
public:
CPort ( ) { }
virtual ~CPort ( ) { }
inline const unsigned int Port ( unsigned int port = UINT_MAX )
{
static_assert( UINT_MAX > 65535 ); // Just to make sure.
if ( port <= 65535 )
m_port = port;
return this->m_port;
}
protected:    
unsigned int m_port = UINT_MAX;
};

而非使用:

int main ( int argc, char** argv )
{
CPort P;
P.Port(80);
unsigned int port = P.Port(); // = UINT_MAX means: Uninitialized 
return 0;
}

我不确定我是否喜欢它。