Прочитав следующий блог:
http://xania.org/200711/ambiguous-overloading
Я начал задавать себе вопрос: «Разве я не всегда должен четко определять свои конструкторы?»
Итак, я начал читать больше, чем узнал эту статью:
http://www.sjbrown.co.uk/2004/05/01/always-use-explicit/
Который показывает другой пример, а также объясняет его мысли за этим.
Но, конечно, это мысли одного блоггера.
Я был бы рад услышать от некоторых из вас, что было бы неплохо, что вы думаете о манере, каков ваш опыт с предметом и несколько примеров в любом случае.
Традиционная мудрость заключается в том, что конструкторы принимая один параметр (явно или эффективно с помощью параметров по умолчанию) должны быть отмечены explicit
, если они не определяют преобразование (std::string
быть конвертируемым из const char*
являясь одним из примеров последнего). Вы сами выяснили причины, по которым неявные преобразования действительно могут сделать жизнь сложнее, чем она должна быть.
Возможно, очевидным исключением является конструктор копирования. Или, возможно, другой способ состоит в том, чтобы считать, что большинство типов являются конвертируемыми из себя и для себя, и что как таковой конструктор копирования не помечен explicit
большую часть времени.
Хотя может показаться, что маркировка всех других видов конструкторов explicit
не больно, я бы с этим поспорил. Потому что пока explicit
не влияет на конструктор, принимающий несколько аргументов в C ++ 03, он имеет влияние в C ++ 11. Чтобы поместить это в код:
struct foo {
explicit foo(int i);
foo(int i, int j);
explicit foo(int i, int j, int k);
};
foo make_foo()
{
/* Not C++11-specific: */
// Error: no conversion from int to foo
return 42;
// Okay: construction, not conversion
return foo(42);
// Okay: constructions
return foo(42, 42);
return foo(42, 42, 42);
/* C++11 specific: */
// Error: no conversion from int to foo
return { 42 };
// Not an error, not a conversion
return { 42, 42 };
// Error! Constructor is explicit
return { 42, 42, 42 };
// Not an error, direct-initialization syntax
return foo { 42, 42, 42 };
}
Я лично нахожу это ненужным многословным в функции, которая возвращает foo
Я должен явно вернуть foo { 42, 42, 42 }
, Я не вижу что explicit
защищает меня от Я очень хочу { initializers... }
синтаксис для обозначения «построить объект из заданных инициализаторов», и explicit
встает на пути этого, спасая меня от ничего. (Поскольку { i }
сводится к i
в контексте инициализации копирования — большую часть времени — я с радостью откажусь от этого.)
Так что я бы сказал, привыкнуть использовать explicit
для одинарных конструкторов, и только те.
Других решений пока нет …