Подтвердить что ты не робот

Почему явно разрешены конструкторы по умолчанию и конструкторы с двумя или более параметрами (не по умолчанию)?

Я понимаю, что конструкторы с одним (не по умолчанию) параметром действуют как неявные преобразователи, которые преобразуют из этого типа параметра в тип класса. Тем не менее, explicit может использоваться для квалификации любого конструктора, без параметров (конструктор по умолчанию) или с двумя или более параметрами (не по умолчанию).

Почему явный разрешен для этих конструкторов? Есть ли какой-нибудь пример, где это полезно для предотвращения неявного преобразования какого-то рода?

4b9b3361

Ответ 1

Одна причина, конечно, в том, что это не повредит.

Одна из причин, в которой это необходимо, - если у вас есть аргументы по умолчанию для первого параметра. Конструктор становится конструктором по умолчанию, но все равно может использоваться как конструктор преобразования

struct A {
  explicit A(int = 0); // added it to a default constructor
};

С++ 0x фактически использует его для конструкторов с несколькими параметрами. В С++ 0x список инициализаторов может использоваться для инициализации объекта класса. Философия

  • если вы используете = { ... }, тогда вы инициализируете объект со своего рода "составным значением", который концептуально представляет абстрактное значение объекта и что вы хотите преобразовать его в тип.

  • если вы используете инициализатор { ... }, вы напрямую вызываете конструкторы объекта, не обязательно указывая преобразование.

Рассмотрим этот пример

struct String {
    // this is a non-converting constructor
    explicit A(int initialLength, int capacity);
};

struct Address {
    // converting constructor
    Address(string name, string street, string city);
};

String s = { 10, 15 }; // error!
String s1{10, 15}; // fine

Address a = { "litb", "nerdsway", "frankfurt" }; // fine

Таким образом, С++ 0x показывает, что решение С++ 03, разрешающее явное использование для других конструкторов, вовсе не было плохой идеей.

Ответ 2

Это, вероятно, просто удобство; нет причин, чтобы его не разрешать, так почему жизнь осложняет генераторы кода и т.д.? Если вы проверили, тогда для процедур генерации кода потребуется дополнительный шаг, проверяющий, сколько параметров генерируется конструктором.

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

Ответ 3

Возможно, это было для поддержки поддержки. Используя explicit в конструкторах с несколькими аргументами, можно избежать непреднамеренного введения неявных преобразований при добавлении аргументов по умолчанию. Хотя я не верю в это; вместо этого я считаю, что на С++ допускается много вещей, чтобы просто не сделать определение языка более сложным, чем оно есть.

Возможно, самым печально известным случаем является возврат ссылки на локальную переменную non static. Это потребует дополнительных сложных правил, чтобы исключить все "бессмысленные" вещи, не затрагивая ничего другого. Так что это просто позволило, получив UB, если вы используете эту ссылку.

Или для конструкторов вам разрешено определять любое количество конструкторов по умолчанию, если их подписи отличаются друг от друга, но с более чем одним из них довольно сложно использовать любой из них по умолчанию.: -)

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

Ну, это будет, в С++ 0x. Поэтому нет веской причины, почему нет. Фактическая причина не допускать explicit на операторы преобразования может быть столь же прозаической, как и надзор, или борьба за получение explicit, принятая в первую очередь, или простая приоритизация времени комитета или что-то еще.

Приветствия и hth.,

Ответ 4

В соответствии с Стандартом кодирования с высоким уровнем целостности С++ вы должны объявить конструктор параметров sinlge как явным, чтобы избежать случайного использования в преобразованиях типов. В случае, если это конструктор с несколькими аргументами, предположим, что у вас есть конструктор, который принимает несколько параметров, каждый из которых имеет значение по умолчанию, преобразование конструктора в какой-то конструктор по умолчанию, а также конструктор преобразования:

class C { 
    public: 
    C( const C& );   // ok copy 
    constructor C(); // ok default constructor 
    C( int, int ); // ok more than one non-default argument 

    explicit C( int ); // prefer 
    C( double ); // avoid 
    C( float f, int i=0 ); // avoid, implicit conversion constructor 
    C( int i=0, float f=0.0 ); // avoid, default constructor, but 
                               // also a conversion constructor 
}; 
void bar( C const & ); 
void foo() 
{ 
    bar( 10 );  // compile error must be 'bar( C( 10 ) )' 
    bar( 0.0 ); // implicit conversion to C 
}

Ответ 5

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

Просто для обсуждения. Я не осведомлен о деталях С++, поэтому мне интересно, рассматривал ли комитет по стандартизации С++ неявное ключевое слово? Это, естественно, будет противоположно явным и делает неявное преобразование типов не по умолчанию.

class SomeClass
{
public:
    implicit SomeClass(int i);
};

Без ключевого слова было бы невозможно выполнить следующее:

SomeClass foo = 6;

Может ли С++ быть чем-то совершенно другим, а не явным?

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