Правильный сеттер и геттер для статической переменной-члена в библиотеке только для заголовков
У меня есть несколько небольших библиотек только для заголовка (важна только часть заголовка). В начальных версиях у меня были некоторые статические члены в классах, определенных в них. Только позже (когда я использовал их в более крупном проекте) мне пришло в голову, что статические члены нарушат ODR. Я хотел, чтобы они были только заголовочными, поэтому определял статические члены отдельно .о файле cpp не могло быть и речи. Одним из хорошо известных решений является использование функции Мейерса синглтона - локальной статическая переменная для каждого статического элемента (как предложено, например, здесь).
Это все хорошо, но поскольку я хочу, чтобы синглет вел себя как членпеременной , я хочу иметь возможность получить и установить значение с помощью сеттеров и геттеров. Но как выглядят геттеры и сеттеры для функций Meyers singletons-локальные статические переменные? Я не смог найти никакого решения этой конкретной проблемы.
Чтобы пояснить, это требования:
- мне нужно поведение статической переменной-члена внутри библиотекитолько для заголовка (поэтому я не могу поместить определения в A .cpp файл)
- мне нужен геттер, который является только геттером (я не должен быть в состоянии изменить Значение, назначив ссылку, возвращаемую геттером)
- я также хочу иметь возможность изменять значение через специальный сеттер.
Правка 1:
Я хотел бы ... объясните , Почему вам это может понадобиться.
Статические переменные в библиотеках, о которых я упоминал, определяют значенияпо умолчанию для некоторых параметров. Однако вместо того, чтобы жестко кодировать эти значения по умолчанию, я хочу дать пользователю возможность установить значения по умолчанию в начале программы, чтобы им не приходилось передавать значения вручную каждый раз, когда они вызывают функцию-член или создают новый экземпляр.
Также, хотя я согласен, что использование термина " Майерс синглтон" в приведенном здесь примере вводит в заблуждение (я просто использую значение int
), ничто не мешает вам использовать эту парадигму с пользовательскими классами, которые вы хотите иметь только один экземпляр. В таких случаях термин "Майерс синглтон" был бы оправдан.
1 ответ:
Решение
#include <iostream> class Foo { private: static int& val() { static int v = 0; return v; } public: Foo() { set_val(14); } Foo(const int _v) { set_val(_v); } // The setter uses the fact that val() // returns a non-const reference, // so we can assign to it. static void set_val(const int _v) { val() = _v; } // A true getter. // Returns const int&, so we cannot assign to it. static const int& get_val() { return val(); } }; int main(void) { std::cout << "val is " << Foo::get_val() << "\n"; Foo f1; // Set the value implicitly via an object constructor std::cout << "val is " << Foo::get_val() << "\n"; Foo f2(5); // Set the value explicitly via an object constructor std::cout << "val is " << Foo::get_val() << "\n"; Foo::set_val(42); std::cout << "val is " << Foo::get_val() << "\n"; // Foo::get_val() = 4; // Doesn't compile, as required return 0; }
Вывод:
val is 0 val is 14 val is 5 val is 42
Установка значения через конструкторы может (и, вероятно, должна) быть опущена. Я просто хотел показать, что это можно сделать. Это много кода только для одной переменной, но не настолько больше, чем для нестатического члена.
Любые мысли, комментарии и предложения приветствуются!