1

我最近遇到了这个类,并对 getter 和 setter 的实现方式感到惊讶。

我以前没有遇到过这种情况,并欢迎一些第二意见。

你认为这是一个好的范式吗?是坏的吗?是邪恶的吗?

标题:

    class Tool
{
public:
    Tool();
    virtual ~Tool();

    bool setName(const std::string &name);
    bool getName(std::string &name) const;

    void clearName();

private:
    std::string m_name;
    bool m_nameSet;

};

cpp文件:

#include "Tool.h"

Tool::Tool()
: m_name("")
, m_nameSet(false)
{
}


Tool::~Tool()
{
}


bool Tool::setName(const std::string &name)
{
    m_name = name;
    m_nameSet = true;
    return (m_nameSet);
}    

bool Tool::getName(std::string &name) const
{
    bool success = false;
    if (m_nameSet)
    {
        name = m_name;
        success = true;
    }
    return (success);
}
4

3 回答 3

2

你为getter选择的方式不流行,程序员更喜欢returngetter中的数据

std::string getName() const;

为什么要在 getter 上重新检查之前设置或具有初始数据的项目?如果要验证数据,请在 setter 上进行验证。

但是,如果您坚持将值返回为“之前设置的名称”,则可以通过以下方式编写第三种方法bool isNameSet() const;

于 2013-03-05T12:16:49.600 回答
2

这看起来很像 C,通常返回状态代码以查看函数是否失败。

然后还有更好的方法来验证是否设置了名称。一个可能是使用 boost::optional 对我来说这是一种更好的方式来声明可能不会始终设置名称的意图。

然而,我想知道是否最好只通过一个将 std::string 作为参数的构造函数来确保始终设置名称。

class Tool
{
public:
  //Constructor already does the right thing
  Tool() = default;
  virtual ~Tool();

  //Use void or return the modified class, akin to operators
  void setName(const std::string& name)
  {
    m_name = name;
  }
  //Alternatively
  Tool& setName(const std::string &name)
  {
    m_name = name;
    return *this;
  }

  //Return const reference to the value if possible, avoids copying if not needed
  //This will fail at run time if name is not set
  //Maybe throw an exception if that is preferred
  const std::string& getName() const
  {
    return *m_name;

    //Or

    if(m_name) return *m_name;
    else throw some_exception;
  }

  //Or return the optional, then calling code can check if name where set or not
  const boost::optional<std::string>& getName() const
  {
    return m_name;
  }


  void clearName()
  {
    m_name = boost::optional<std::string>();
  }

private:
  boost::optional<std::string> m_name;
};
于 2013-03-05T12:56:54.120 回答
0

我不会称之为范式。这似乎是架构的解决方案,其中一个字段可能处于未指定状态(为什么不呢?有时这是一个理智的要求)。不过,我不太喜欢这个解决方案,因为 getter 应该返回值(对称地,setter 应该设置它)并且约定通常需要特定的原型:

Type GetValue();
SetValue (const Type & newValue);
or
SetValue (Type & newValue);
or
SetValue (Type newValue);

您应根据情况选择三个二传手之一,通常第一个或第二个适合。

如果一个字段可能处于未指定状态,我会选择另一种方法,正如 M M. 在他的回答中所建议的那样,我将冒昧地提供一个示例:

class C
{
private:
    int field;
    bool fieldSet;

public:
    C()
    {
        field = 0;
        fieldSet = false;
    }

    bool IsFieldSet()
    {
        return fieldSet;
    }

    int GetField()
    {
        if (!fieldSet)
            throw std::exception("Attempt to use unset field!");

        return field;
    }

    void SetField(const int newValue)
    {
        field = newValue;
        fieldSet = true;
    }
};

但请注意,我不会将这种实现 getter 的方式称为evil。使用起来可能会不舒服。

于 2013-03-05T12:38:44.997 回答