Парадигма получателя/установщика С++

Недавно я наткнулся на этот класс и был удивлен тем, как реализованы геттеры и сеттеры.

Я не сталкивался с этим раньше и приветствовал бы некоторые другие мнения.

Как вы думаете, это хорошая парадигма? Разве плохо? Это зло?

Заголовок:

    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;

};

СРР-файл:

#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);
}

person user1414413    schedule 05.03.2013    source источник
comment
Что именно вы называете хорошей или плохой парадигмой? Хранение информации, было ли установлено имя? Это явно зависит от архитектуры.   -  person Spook    schedule 05.03.2013


Ответы (3)


Способ, который вы выбрали для геттера, не популярен, программисты предпочитают return данные из геттера

std::string getName() const;

Почему элемент, который был установлен ранее или имеет начальные данные, должен быть перепроверен на геттере? Если вы хотите проверить данные, проверьте их на сеттере.

Однако, если вы настаиваете на том, чтобы вернуть значение как «имя задано ранее», вы можете написать третий метод с помощью bool isNameSet() const;

person masoud    schedule 05.03.2013
comment
Если вы хотите проверить данные, проверьте их на сеттере. Если сеттер никогда не вызывается, как вы что-то проверяете? Как вызывающая сторона геттера узнает, было ли установлено значение или нет? (Я не знаю, зачем звонящему это знать, но, видимо, это так) - person Jonathan Wakely; 05.03.2013
comment
Хорошо, мы можем вернуть значение по умолчанию. и вызывающий должен проверить isNameSet() раньше. Однако все это зависит от вкуса программиста. Я видел этот шаблон в Qt. - person masoud; 05.03.2013

Это очень похоже на 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;
};
person AxelOmega    schedule 05.03.2013

Я бы не назвал это парадигмой. Кажется, это решение для архитектуры, где поле может находиться в неопределенном состоянии (почему бы и нет? Иногда это разумное требование). Хотя мне не очень нравится это решение, потому что геттер должен возвращать значение (симметрично, предполагается, что сеттер его устанавливает), а соглашение обычно требует определенных прототипов:

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

Вы должны выбрать одного из трех сеттеров в зависимости от ситуации, обычно подходит первый или второй.

Если поле может находиться в неопределенном состоянии, я бы выбрал другой подход, как предлагает М. М. в своем ответе, я позволю себе привести пример:

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;
    }
};

Заметьте, однако, что я бы не назвал этот способ реализации геттеров злом. Может просто неудобно пользоваться.

person Spook    schedule 05.03.2013