使用类似Set / Get的方法或GetSet组合函数

时间:2018-07-23 20:48:11

标签: c++

我很喜欢在课堂上使用C#风格的GetsSets。然后,我遇到以下示例:注意端口类中第二个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

2 个答案:

答案 0 :(得分:1)

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

通常的原因是改进封装,以便能够更好地调试代码(您可以非常轻松地记录所有设置)。您还可以隐藏实现详细信息(可能有“ getter”,但后面不必有任何 one 字段)。

我的观点是,如果您尝试保存编写这些函数时的击键操作,并且愿意通过在外部返回对您的私有变量的可修改引用来破坏封装,那么最好使用普通的公共字段。但是,如果您以后可以看到getter和setter很有用,则一定要谨慎地编写它们以封装代码。毕竟,它是您正在设计的类的API。

要详细说明您返回参考的具体示例,以便用户以这种方式设置值。您有点违反二传手的目的。

  • 您无法检查用户提供的值,例如记录某些特殊情况。
  • 您甚至都不真正知道用户何时设置值,因为他可以保存参考以供以后更改。
  • 如果只有一个方法同时进行获取和设置,则将完全丢弃对象的 constness (您不能只是 get 的值) const实例)

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

对于C#,在C#中有大量的自动属性语法糖,它们几乎没有花费,并且在需要时易于编写和重写。但是请记住,这些不会破坏封装。

答案 1 :(得分:0)

如果您在可接受范围内有特定范围的值,则仍可以使用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;
}

我不确定是否喜欢它。