Если у меня есть конструктор с 2 обязательными параметрами и 4 необязательными параметрами, как я могу избежать написания 16 конструкторов или даже 10 конструкторов, которые мне пришлось бы писать, если бы я использовал параметры по умолчанию (что мне не нравится, потому что это плохая самодокументация)? Существуют ли какие-либо идиомы или методы, использующие шаблоны, которые я могу использовать, чтобы сделать его менее утомительным? (И проще в обслуживании?)избегая скуки необязательных параметров
ответ
Возможно, вас заинтересует Named Parameter Idiom.
Чтобы подвести итог, создайте класс, который содержит значения, которые вы хотите передать своим конструкторам. Добавьте метод для установки каждого из этих значений, и каждый из них должен сделать return *this;
в конце. У вас есть конструктор в своем классе, который ссылается на этот новый класс. Это можно использовать так:
class Person;
class PersonOptions
{
friend class Person;
string name_;
int age_;
char gender_;
public:
PersonOptions() :
age_(0),
gender_('U')
{}
PersonOptions& name(const string& n) { name_ = n; return *this; }
PersonOptions& age(int a) { age_ = a; return *this; }
PersonOptions& gender(char g) { gender_ = g; return *this; }
};
class Person
{
string name_;
int age_;
char gender_;
public:
Person(const PersonOptions& opts) :
name_(opts.name_),
age_(opts.age_),
gender_(opts.gender_)
{}
};
Person p = PersonOptions().name("George").age(57).gender('M');
Как бы вы сделали эту работу в конструкторе? Используя 'return this' в методе конструктора? –
Очевидно, вы ничего не можете вернуть из конструктора. Но вы можете использовать копию, например 'Foo f = Foo(). Option1(). Option2();' например. В примере в ссылке используется отдельный класс для фактического создания. –
@Robert важно заметить, что правая сторона начинается с 'PersonOptions', а не' Person'. Это создает предположительно легкий объект, а затем имеет ряд вызовов методов для установки свойств на значения, отличные от значений по умолчанию. Тогда есть ctor с именем 'Person (const PersonOptions &)' и ta da. Создание экземпляра объекта (например, 'PersonOptions()') оставляет «* this» в текущем контексте, так что вы можете сразу его отключить .method(). Однако каждый метод все равно должен «возвращать» это, чтобы иметь возможность цепочки после него. –
Что делать, если вы создали объект параметра, содержащий все поля? Тогда вы можете просто передать это и просто установить любые поля, в которых вы нуждаетесь. Там, вероятно, название для этой модели, не уверен, что это такое, хотя ...
UPDATE:
код может выглядеть несколько так:
paramObj.x=1;
paramObj.y=2;
paramObj.z=3;
paramObj.magic=true;
... //set many other "parameters here"
someObject myObject = new someObject(paramObj);
и внутри someObject
конструктора вы можете установить значения по умолчанию для вещей, которые еще не были установлены (или вызвать ошибку, если это было обязательно).
Честно говоря, я не являюсь большим поклонником этого решения, но я использовал его один или два раза, когда paramObj
имел смысл, содержавший набор данных, которые обычно сошлись (чтобы мы могли использовать его больше просто конструкторы), и это было лучше, чем несколько конструкторов. Я обнаружил, что это было уродливо, но это сработало, YMMV.
... и этот объект параметра задает значения по умолчанию в своем конструкторе по умолчанию. – Danvil
Почему это лучше, чем просто создавать исходные объекты и свойства настройки? –
@Johannes: Разве это не Идиома Имени, которую Фред Ларсон упоминает в своем ответе? –
И теперь для «Boost, есть кое-что для него» ответ:
Boost Parameter Library, кажется, хорошо подходит для вашего использования.
Все новые для C++ 17
#include <optional>
using optional_int = std::optional<int>;
class foo {
int arg0, arg1; // required
int arg2, arg3; // optional
const int default_2 = -2;
const int default_3 = -3;
public:
foo(int arg0, int arg1, optional_int opt0 = {}, optional_int opt1 = {})
: arg0(arg0), arg1(arg1)
, arg2(opt0.value_or(default_2))
, arg3(opt1.value_or(default_3))
{ }
};
int main() {
foo bar(42, 43, {}, 45); // Take default for opt0 (arg2)
return 0;
}
У меня есть кубический сплайн реализации, что позволяет пользователю необязательно указывать первую производную либо на левом конце, правый конец, или обоих. Если производная не указана, то действующий код вычисляет один, считая, что вторая производная равна нулю (так называемый «естественный сплайн»). Вот фрагмент для левого конца.
// Calculate the second derivative at the left end point
if (!left_deriv.has_value()) {
ddy[0]=u[0]=0.0; // "Natural spline"
} else {
const real yP0 = left_deriv.value();
ddy[0] = -0.5;
u[0]=(3.0/(x[1]-x[0]))*((y[1]-y[0])/(x[1]-x[0])-yP0);
}
- 1. Python необязательных параметров
- 2. Perl несколько необязательных параметров
- 3. Обработка необязательных параметров запроса
- 4. Передача необязательных параметров
- 5. AngularJS $ ресурсные несколько необязательных параметров
- 6. Обработка необязательных параметров в главном
- 7. Изменение htaccess для необязательных параметров
- 8. Обработка необязательных параметров в JavaScript
- 9. Htaccess для нескольких необязательных параметров
- 10. Rails маршрутизирует несколько необязательных параметров
- 11. несколько необязательных параметров в Angular.js
- 12. Скуки, возвращающиеся как ошибка имени
- 13. C# Несколько изделий из скуки
- 14. C# хранимая процедура без прохождения необязательных параметров
- 15. Сценарий оболочки для принятия необязательных параметров
- 16. Цепочка конструктора или использование названных/необязательных параметров
- 17. Оптимальная передача необязательных параметров в запрос
- 18. MVC-обработчик для неизвестного количества необязательных параметров
- 19. Передача необязательных параметров в асинхронном делегатом вызовы
- 20. Лучший способ определения необязательных параметров запроса
- 21. sql search query для нескольких необязательных параметров
- 22. как написать запрос для необязательных параметров
- 23. Rails: объединение необязательных параметров в запрос
- 24. Как использовать call_user_func_array для необязательных параметров
- 25. несколько необязательных параметров в Синатра маршруте
- 26. Параметр Params при использовании необязательных параметров
- 27. Несколько необязательных параметров маршрутизация атрибутов api api
- 28. Запрос модели Rails с множеством необязательных параметров
- 29. Легкий модуль JavaScript для необязательных/стандартных параметров
- 30. Добавление необязательных параметров с Nhibernate и QueryOver
Вы уверены, что ваш класс не пытается сделать слишком много? –
@Johannes: Он хочет, чтобы пропустить say d, не заставляя вызывающего абонента узнать его значение по умолчанию. – Danvil
@John: Я вижу, что вы получаете, но параметры могут быть свойствами. Например, у меня есть класс GUI Button, который имеет множество свойств, таких как изображение, текст, размер, цвет и т. Д., Но я не чувствую, что это «слишком много». IMHO, Кнопки служат очень конкретной цели и легко вписываются в один класс, где пользователь сразу узнает, что делает класс. – Kyle