Шаблоны для сеттеров и геттеров - PullRequest
8 голосов
/ 16 ноября 2010

Я не знаком с шаблонами, но мне интересно, можно ли использовать их для методов установки и получения. Например, в этой ситуации:

double exmlClass::getA(void) const
{
    return a_;
}



void exmlClass::setA(const double& a)
{
    a_ = a;
}



double exmlClass::getB(void) const
{
    return b_;
}

Как видите, методы почти одинаковы, за исключением того, что они ссылаются на другие частные переменные (a_, b_, c_). Есть ли более элегантный способ написания этих функций или в таких ситуациях принято делать, как описано выше? И если это обычное использование шаблонов, я был бы признателен за пример того, как вы будете использовать их в приведенном выше коде.

Другой вопрос, который я хотел бы задать, - как правильно объявлять методы получения и установки. Это хороший стиль кодирования?

double getA(void) const;
void setA(const double& a);

double getB(void) const;
void setB(const double& b);

double getC(void) const;
void setC(const double& c);

Я имею в виду, должны ли геттеры всегда быть константными, а сеттеры принимают в качестве аргумента ссылку на объект, а не копируют его, что, вероятно, будет немного медленнее?

Ответы [ 6 ]

4 голосов
/ 16 ноября 2010

Аро скептикам!

Boost.Fusion.Map - это то, что вы ищете в качестве основы.

namespace result_of = boost::fusion::result_of;

class MyClass
{
public:
  struct AType {};
  struct BType {};
  struct CType {};

  template <typename Type>
  typename result_of::at< DataType, Type >::type &
  access(Type) { return boost::fusion::at<Type>(mData); }

  template <typename Type>
  typename result_of::at< DataType, Type >::type const &
  get(Type) const { return boost::fusion::at<Type>(mData); }

  template <typename Type>
  void set(Type, typename result_of::at< DataType, Type >::type const & v)
  {
    boost::fusion::at<Type>(mData) = v;
  }

private:
  typedef boost::fusion::map <
    std::pair<AType, int>,
    std::pair<BType, std::string>,
    std::pair<CType, float> > DataType;
  DataType mData;
};
2 голосов
/ 16 ноября 2010

разрабатывайте свои программы таким образом, чтобы меньше требовались геттеры и сеттеры. Вы можете создать их с помощью макроса или реализовать некий синтаксис (что возможно, но всегда есть вещи, которые не работают правильно). Тем не менее, я полагаю, что лучше всего написать и написать средства доступа, когда они нужны, или сгенерировать их с помощью вашей IDE.

Что касается вашего второго вопроса, вы должны использовать его, по крайней мере, для типа объекта, он вам на самом деле не нужен для примитивов. Лично я не использую его, если мне все равно нужна копия объекта, однако другие могут утверждать, что лучше сделать это явно.

0 голосов
/ 16 ноября 2010

Технически возможно создать единственный шаблон функции exmlClass::set<PMF> так, чтобы exmlClass::set<&exmlClass::a_> был действительным.Однако какой в ​​этом смысл?

0 голосов
/ 16 ноября 2010

Я не вижу способа, чтобы шаблоны могли напрямую помочь вам компактифицировать ваши пары геттер / сеттер, если вы не хотите обернуть своих членов внутри шаблонных классов доступа, таких как this .Другой возможностью является использование макроса #define для эмуляции свойств C # (если макросы не пугают вас или кого-либо, кто читает ваш код).

Возвращают ли ваши получатели (const) ссылки на члены, возвращают ли указатели членам илиКопировать их зависит от нескольких факторов.Вы должны решить, стоит ли копировать их (с точки зрения производительности), семантически ли имеет смысл копировать их, и должна ли быть возможность, что информация, которую вы возвращаете, переживет класс, который выполучить его от (если вы вернете указатель / ссылку на член, он останется висящим, как только вы удалите свой объект).И я бы использовал указатели на ссылки, если вы хотите, чтобы член был нулевым.

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

0 голосов
/ 16 ноября 2010

Нет, вы не можете определить какой-либо шаблон, который может создавать функции или подобные функции с неограниченным набором имен, таких как getA, getB, ....

Макрос может сделатьэто, но это еще хуже идея.

Обычно я передаю / возвращаю объект класса по константной ссылке, но простые встроенные типы, такие как double, просто по значению:

public:
  const ClassType& getObj() const;
  void setObj(const ClassType& obj);
  double getNum() const;
  void setNum(double num);
0 голосов
/ 16 ноября 2010

Теоретически вы могли бы:

template<typename A, typename B, typename C>
class Object
{
private:
    A _a;
    B _b;
    C _c;

public:
    Object()
    {
    };  // eo ctor

    // properties

    A getA() const {return(_a);}
    void setA(const A& _val) {_a = _val;}

    // etc for B & C
}; // eo class Object

    // .....

    Object<int, double, char> myObject;

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

Во-вторых, это определяет 3. Сколько вам нужно для ваших объектов?1, 2, 4, 9?

В-третьих, геттеры / сеттеры должны быть названы в соответствии с их функцией:

getName()
getAddress()
getMovie()

Звучит так, будто вы просто хотите сэкономить на наборе текста, а не оправдывать усложнение дизайна.*

Что касается вашей второй точки, верните ссылку на объекты (предпочтительно const), но не беспокойтесь о маленьких, целочисленных типах POD (Plain-Old-Data), таких как int, char, bool и т. Д..

...