LINUX.ORG.RU

using ctor and cast operator as accessors

 


0

3

Есть кодовая база, в которой нужно закрыть доступ к полю структуры. Использование классических get()/set() дело понятное и привычное. Но есть еще один способ реализовать свойства - с помощью конструкторов и операторов приведения.

ВАЖНО: в структуре только одно поле. по факту это замена встроенного типа на свой тип с более сложной логикой.

Классика

struct Value
{
    float getValue()        { return _value; }
    void  setValue(float v) { _value = v; }
private:
    float _value;
}

Через конструктор и оператор приведения

struct Value
{
    float()        { return _value; }
    Value(float v) { _value = v; }
private:
    float _value;
}

Вопрос - какие достоинства и недостатки у этих двух способов? Для меня пока плюс второго варианта в том, что мне не нужно будет модифицировать уж существующий код и я пока на его стороне. Но нет ли там каких подводных камней?

Что если у тебя в структуре будут два значения одного типа? В первом варианте это просто getValue1(), getValue2(), а во втором?

Crocodoom ★★★★ ()
Последнее исправление: Crocodoom (всего исправлений: 1)
Ответ на: комментарий от Crocodoom

Да, не уточнил этот важный момент - подразумевается что только одно значение в типе.

Если несколько значений одного типа тогда только первый вариант.

yetanother ★★ ()
Ответ на: комментарий от yetanother

подразумевается что только одно значение в типе.

А также подразумевается, что ни одна из структур не является шаблонной (что тоже отметает второй вариант)?

И я кстати не понял, почему

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

В обоих же случаях тебе придётся добавлять свои функции в старую кодовую базу

Crocodoom ★★★★ ()
Ответ на: комментарий от Crocodoom

А также подразумевается, что ни одна из структур не является шаблонной (что тоже отметает второй вариант)?

Да, не шаблонные. Только не понял с ходу почему это отметет второй вариант?

template<typename T>
struct Value
{
    T()        { return _value; }
    Value(T v) { _value = v; }
private:
    T _value;
}
разве не будет работать или что-то другое имеется в виду?

В обоих же случаях тебе придётся добавлять свои функции в старую кодовую базу

Ну новый тип то добавлять нужно будет в обоих случаях, да. Но во втором варианте не нужно будет в местах обращения к переменным/полям данного типа прописывать getValue()/setValue(). Я уже так сделал в порядке эксперимента, все работает замечательно, поэтому решил уточнить, вдруг я что-то критически важное упускаю. С++ то он же такой. Вдруг я уже взвел курок и направил оба ствола себе в ногу?

yetanother ★★ ()

Курсач пиши сам.

/thread

anonymous ()
Ответ на: комментарий от yetanother

ВАЖНО: в структуре только одно поле. по факту это замена встроенного типа на свой тип с более сложной логикой.

А, ну это всё меняет. Тогда второй вариант возможен (и я так тоже делал).

Crocodoom ★★★★ ()

Классика

Для java. RAII идёт лесом. isNull не забудь добавить.

onhydro ()
Ответ на: комментарий от Crocodoom

ВАЖНО: в структуре только одно поле. по факту это замена встроенного типа на свой тип с более сложной логикой.

А, ну это всё меняет. Тогда второй вариант возможен (и я так тоже делал).

Ну я после вопроса про вторую величину того же типа и понял в чем различие между вариантами. А то терзали смутные сомнения. Благодарю за ответ.

yetanother ★★ ()

Небольшая неточность в коде (на самом деле 2)

struct Value
{
  operator float() const { return _value; }
  // ...
}; // третья?

Я б еще по принципу «least surprise» сделал explicit:

explicit operator float() const { return _value; }
explicit Value(const float v) : _value{v} {}

И в качестве профилактики UB (связанной с lifetime обьекта) и (возможной) оптимизации еще б приправил constexpr:

struct Value {
  constexpr explicit Value(const float v) : _value{v} {}
  constexpr explicit operator float() const { return _value; }
  // ...
};

KennyMinigun ★★★★★ ()
Последнее исправление: KennyMinigun (всего исправлений: 3)
Ответ на: комментарий от KennyMinigun

Всегда приятно учится у знающих людей. Внимание к мелочам - то что делает человека профессионалом. Не знаю только куда плюсик поставить или как тут по другому спасибо сказать?

yetanother ★★ ()

ВАЖНО: в структуре только одно поле

Зачем тебе такая структура?... В остальном template<typename T> struct some_usefull_struct { ... }

invy ★★★★★ ()
Последнее исправление: invy (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

explicit

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

i-rinat ★★★★★ ()
Ответ на: комментарий от i-rinat

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

верно. Но мне важнее было понять нет ли ошибки в концепции. Потому что про геттеры/сеттеры все знают, а про второй вариант я нашел только несколько упоминаний и одно из них осторожно рекомендует использовать второй вариант только если у вас много легаси, а так дескать лучше геттеры/сеттеры. И при этом не слова почему так.

И судя по тому, что никто не сказал, что так нельзя, значит можно.

yetanother ★★ ()
Ответ на: комментарий от invy

Зачем тебе такая структура?

Замена встроенного типа на свой, с более сложной логикой. Бинарная и текстовая сериализация, эмуляция контрактов/инвариантов и другие плюшки. Сами структуры генерируются автоматически на основе DSL. И вот хочется включить их в проект как можно менее интрузивно.

yetanother ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.