Missing explicit keyword

Конструктор, пропускающий explicit спецификатор

Описание

Пропавшие без вести explicit ключевое слово происходит, когда объявление конструктора не использует explicit спецификатор. explicit спецификатор предотвращает неявное преобразование из переменной другого типа к текущему типу класса.

Дефект применяется:

  • Конструкторы с одним параметром.

  • Конструкторы, где у всех кроме параметров есть значения по умолчанию.

    Например, MyClass::MyClass(float f, bool b=true){}.

Риск

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

Неявное преобразование может произойти, например, когда функция принимает параметр типа класса, но вы вызываете функцию с аргументом другого типа.

Фиксация

Для лучшей удобочитаемости вашего кода и предотвратить неявные преобразования, в объявлении конструктора, помещают explicit ключевое слово перед именем конструктора.

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

Примеры

развернуть все

class MyClass {
public:
    MyClass(int val);
private:
    int val;
};

void func(MyClass);

void main() {
    MyClass MyClassObject(0);

    func(MyClassObject);   // No conversion
    func(MyClass(0));      // Explicit conversion
    func(0);               // Implicit conversion
}

В этом примере, конструкторе MyClass не объявляется explicit. Поэтому вызов func(0) может выполнить неявное преобразование из int к MyClass.

Коррекция — использует explicit Ключевое слово

Одна возможная коррекция должна объявить конструктора MyClass как explicit. Если операция в вашем коде выполняет неявное преобразование, компилятор генерирует ошибку. Поэтому использование explicit ключевое слово, вы обнаруживаете непреднамеренные преобразования типов на этапе компиляции.

Например, в функциональном main ниже, если вы добавляете оператор func(0); это выполняет неявное преобразование, код не компилирует.

class MyClass {
public:
    explicit MyClass(int val);
private:
    int val;
};

void func(MyClass);

void main() {
    MyClass MyClassObject(0);

    func(MyClassObject);   // No conversion
    func(MyClass(0));      // Explicit conversion
}
class Month {
    int val;
public:
    Month(int m): val(m) {}
    ~Month() {}
};

class Day {
    int val;
public:
    Day(int d): val(d) {}
    ~Day() {}
};

class Year {
    int val;
public:
    Year(int y): val(y) {}
    ~Year() {}
};

class Date {
    Month mm;
    Day dd;
    Year yyyy;
public:
    Date(const Month & m, const Day & d, const Year & y):mm(m), dd(d), yyyy(y) {}
};

void main() {
    Date(20,1,2000); //Implicit conversion, wrong argument order undetected
}

В этом примере, конструкторах для классов Monthдень и Year не имейте explicit ключевое слово. Они позволяют неявное преобразование из int переменные к Monthдень и Year переменные.

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

Коррекция — использует explicit Ключевое слово

Если вы используете explicit ключевое слово для конструкторов классов Monthдень и Year, вы не можете вызвать Date конструктор с неправильным порядком аргументов.

  • Если вы вызываете Date конструктор с int переменные, ваш код не компилирует потому что explicit ключевое слово предотвращает неявное преобразование из int переменные.

  • Если вы вызываете Date конструктор с аргументами, явным образом преобразованными в Monthдень и Year, и имейте неправильный порядок аргументов, ваш код не компилирует из-за несоответствия типа аргумента.

class Month {
    int val;
public:
    explicit Month(int m): val(m) {}
    ~Month() {}
};

class Day {
    int val;
public:
    explicit Day(int d): val(d) {}
    ~Day() {}
};

class Year {
    int val;
public:
    explicit Year(int y): val(y) {}
    ~Year() {}
};

class Date {
    Month mm;
    Day dd;
    Year yyyy;
public:
    Date(const Month & m, const Day & d, const Year & y):mm(m), dd(d), yyyy(y) {}
};

void main() {
    Date(Month(1),Day(20),Year(2000)); 
    // Date(20,1,2000); - Does not compile
    // Date(Day(20), Month(1), Year(2000)); - Does not compile
}

Информация о результате

Группа: Объектно-ориентированный
Язык: C++
Значение по умолчанию: 'off'
Синтаксис командной строки: MISSING_EXPLICIT_KEYWORD
Удар: низко

Введенный в R2015b