2013-03-05 3 views
1

Недавно я столкнулся с этим классом и был удивлен тем, как были установлены геттеры и сеттеры .Парадигма getter/setter C++

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

Считаете ли вы, что это хорошая парадигма? Is is bad? Это зло?

Заголовок:

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); 
} 
+0

О чем вы говорите, как о хорошей или плохой парадигме? Хранение информации, было ли задано имя? Это явно характерно для архитектуры. – Spook

ответ

2

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

std::string getName() const; 

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

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

+0

_ «Если вы хотите проверить данные, подтвердите их на установщике». _ Если сеттер никогда не вызывается, как вы подтверждаете что-либо? Как вызывающий абонент узнает, установлено ли значение или нет? (Я не знаю, почему вызывающий должен это знать, но, видимо, это так) –

+0

Хорошо, мы можем вернуть значение по умолчанию.и вызывающий должен проверить 'isNameSet()' раньше. Однако все они зависят от вкуса программиста. Я видел эту схему в Qt. – deepmax

0

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

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

Примечание, однако, что Я бы не назвал этот способ внедрения геттеров evil. Это может быть просто неудобно использовать.

1

Это похоже на 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; 
}; 
Смежные вопросы