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

Как правильно использовать конструкторы преобразования?

Я читал, что компиляторы С++ могут неявно преобразовывать типы, когда предусматриваются преобразования конструкторов или операндов. Я действительно нашел пример кода, который выглядит примерно так:

class Dog{
    private:
       string name;
    public:
        Dog(string n):name(n){} //This as the converting constructor
}

int main(){
    Dog d = "rover";
}

Всякий раз, когда я запускаю этот код, компилятор выдает сообщение об ошибке:

преобразование из 'const char [6] в нескалярный тип' Собака запросила    Собака d = "rover";

При компиляции я добавляю параметр компилятора -std=c++11, поэтому он не должен быть о версии на С++, верно?
Примеры, которые я нашел в Интернете (по крайней мере для меня), выглядят совершенно одинаковыми, поэтому я не знаю, что здесь происходит. Мои данные об этой теме приводятся, например, из этого видео: Преобразовать конструктор и перегружать операторы - thenew moston

4b9b3361

Ответ 1

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

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

Dog d1 ("rover");
Dog d2 = "rover";

Случай d2 пытается преобразовать литерал в Собаку, а затем скопировать (переместить) это на d2. Но это будет двойное преобразование: const char* - string, а затем string - Dog.

Конструкция d1 создает d1, передавая аргумент конструктору, поэтому только одно преобразование const char* в string. (В обоих случаях продвижение const char [6] до const char* тоже есть, но не учитывается только для "только одного", находящегося в другой категории.)

Инициализация копирования не указывает "rover" в качестве аргумента конструктора. В нем говорится: "Здесь есть что-то, но здесь нужен Dog". здесь есть правая часть синтаксиса объявления copy-init, а не какая-либо идентифицируемая функция. Компилятор, чем найти юридическое преобразование.

В случае с прямым инициализацией вы просто указываете параметры для функции (конструктора). Компилятор преобразует то, что вы дали ему в объявленный тип аргумента.

Ответ 2

Примечание "rover" не std::string, оно const char[6] (с нулевым символом в конце) (может затухать до const char*), чтобы сделать работу Dog d = "rover";, "rover" необходимо преобразовать в std::string, а затем преобразуется в Dog.

Но пользовательское преобразование не будет рассматриваться дважды в одном неявном преобразовании.

(акцент мой)

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

Вы можете преобразовать "rover" в std::string явно, чтобы он работал.

Dog d = std::string("rover");

Ответ 3

Вам нужен другой конструктор, который позволяет вам построить из const char*:

Dog(const char* n):name(n){}

Помните, что "rover" не является std::string, и тип не будет использоваться для использования конструктора преобразования неявно. Как отметил @songyuanyao в своем ответе, преобразование будет сделано только один раз.

Другой вариант - написать:

Dog d = std::string("rover");