0

Избежание неявного преобразования в конструкторе: ключевое слово 'explicit' здесь не помогает

13

Задача заключается в том, чтобы запретить создание объекта класса A при передаче параметра типа double, даже если конструктор помечен как explicit. Я хочу, чтобы объекты класса A могли создаваться только при передаче целочисленного параметра, например, A a1 = A(10);.

Вот мой код:

#include <iostream>

class A
{
public:
    explicit A(int a)
    {
        num = a;
    }

    int num;
};

int main()
{
    A a1 = A(10.0);
    std::cout << a1.num;
    return 0;
}

В текущей реализации я могу инициализировать объект A, используя двойное значение A(20.2) или даже A(10.0), что не соответствует желаемому поведению. Как я могу изменить класс A, чтобы запретить создание объектов с параметрами, отличными от целых чисел?

5 ответ(ов)

0

Ваша ошибка происходит из-за использования удаленного конструктора в структуре A. Давайте разберемся с вашим кодом и объясним, почему это происходит.

В структуре A вы определили явный конструктор A(int a), который принимает целое число. Также вы добавили шаблонный конструктор A(T) и пометили его как удаленный с помощью = delete;. Это значит, что любой вызов конструктора с типом, отличным от int, будет приводить к ошибке компиляции.

В вашем коде есть две строки, которые создают объекты класса A:

//A a1 = A(10.0); // ошибка
A a2 = A(10); // нормально

Первая строка закомментирована и вызывает ошибку, так как вы пытаетесь создать объект A с типом double (вызов A(10.0)), что приводит к активации удаленного конструктора A(T). Таким образом, компилятор генерирует ошибку, сообщая, что вы пытаетесь использовать удаленную функцию.

Вторая строка A a2 = A(10); компилируется успешно, так как вы передаете целочисленное значение 10, которое подходит для явного конструктора A(int).

Если вам нужно запретить использование других типов, кроме int, такой подход совершенно корректен. Ваше использование explicit и = delete; для шаблонного конструктора позволяет точно ограничить доступные типы при создании экземпляров A.

Таким образом, если вам нужно создать объект A, просто убедитесь, что вы используете целочисленные типы, как это сделано в случае A(10).

Если у вас есть еще вопросы или нужно больше объяснений, не стесняйтесь задавать их!

0

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

template <typename T>
A(T) = delete;

Это предотвратит создание экземпляров класса из любых типов, кроме int.

0

Вы можете добавить, что A(double) = delete — это новшество, введенное в C++11.

Если по каким-то причинам вы не можете использовать этот относительно новый конструктив, вы можете просто объявить конструктор как private, как показано ниже:

class A {
  public:
    A(int);
  private:
    A(double);
};

Таким образом, конструктор A(double) будет недоступен для создания объектов этого класса вне его определения.

0

Чтобы явно удалить конструктор для типа double, вы можете использовать следующий синтаксис:

A(double) = delete;

Это запрещает создание объектов класса A с параметром типа double. Если вам нужно добавить конструктор для типа float, вы можете сделать это следующим образом:

A(float) {
    // Реализация конструктора для типа float
}

Таким образом, вы ограничите использование конструктора только для типов float и всех остальных, кроме double. Не забудьте уточнить, если у вас есть другие требования или ограничения для вашего класса.

0

Вы можете использовать флаг -Wconversion компилятора gcc, который будет генерировать предупреждение при неявном преобразовании значения типа float в int. Также добавьте флаг -Werror, чтобы преобразовать это предупреждение (а также все остальные) в ошибку компиляции. Это поможет вам избежать потенциальных проблем с потерей данных при таких преобразованиях.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь