=, как компилятор узнает
использовать конструкторы?#include <string>
class Person
{
public:
std::string name;
Person(const char* full_name) : name(full_name) {}
};
int main()
{
Person p1("Jibel Sadeghi"); // This is ok because we declared the constructor with a const char*, but...
/* When we didn't overload the '=' operator for 'const char*',
how the next lines don't have any errors? */
p1 = "Ben Sadeghi";
}
Вы только что сообщили компилятору два способа создания Person из других типов, поэтому он делает это при необходимости. Вы можете сделать конструкторы explicit, если хотите ограничить их использование.
Я не минусовал. Это был просто общий совет.
@Jibel - Вы не представляете, как называют людей, когда они объясняют свое отрицательное мнение. Но не нужно много времени, чтобы понять, что лучше не делать этого.
@Jibel Хорошо, не стоит включать это в свой вопрос.
способы создания, Мы ничего не создаем в строках 18 и 20, а просто устанавливаем значения @BoP
Некоторые конструкторы будут неявно доступны, если вы не создадите никаких собственных конструкторов, включая неявный конструктор копирования/присваивания.
Следующий трюк: сделайте минимально воспроизводимый пример.
Поскольку вы не определили свой конструктор как explicit, он называется конструктором преобразования.
@heapunderrun Это полностью меняет для меня значение конструктора, я думал, что конструктор можно использовать только при объявлении класса.
Компилятор умен. Если ему нужен X и у него есть Y, он будет искать способы превратить Y в X. Пути от Y к X иногда могут быть неожиданными.
Я считаю, что StackOverflow рекомендует голосовать против без объяснения причин. (У меня нет под рукой ссылки.) В противном случае указание причины часто приводит к неконструктивному обсуждению (или бурному обсуждению) в комментариях, а это не дискуссионный форум.





Разве конструктор не вызывается только при определении переменной?
Нет. Конструктор используется при создании объекта (экземпляра класса).
Этот объект может храниться в переменной, или в элементе массива, или динамически распределяться, или (в случае, если у вас есть здесь) временный объект.
Если мы не определили ни одного оператора =, как компилятор узнает, что нужно использовать конструкторы?
В вашем классе есть оператор присваивания копирования по умолчанию с подписью
Person& Person::operator=(const Person& assign_from);
и оператор присваивания перемещения по умолчанию с подписью
Person& Person::operator=(Person&& move_assign_from);
Когда компилятор пытается скомпилировать
p1 = "Ben Sadeghi";
он видит, что ему нужен Person::operator=(), просматривает всех кандидатов (по умолчанию два, потому что вы не указали ни одного) и для каждого кандидата пытается преобразовать фактические параметры в типы формальных параметров.
Для присваивания копии формальный параметр имеет тип const Person&, фактический параметр имеет тип const char[12], и существует неявный конструктор, способный выполнять преобразование. Так можно назвать Person::Person(const char*), а затем Person& Person::operator=(const Person&).
Для назначения перемещения формальный параметр имеет тип Person&&, фактический параметр имеет тип const char[12], и существует неявный конструктор, способный выполнять преобразование. Так можно назвать Person::Person(const char*), а затем Person& Person::operator=(Person&&).
Аргумент Person&& лучше подходит для временного человека, чем const Person&, поэтому в конце выбирается последовательность Person::Person(const char*), за которой следует Person& Person::operator=(Person&&).
@fabian: Ах да, перемещение по умолчанию было бы отклонено, если бы какой-либо из operator= был объявлен пользователем или если бы конструктор копирования был объявлен пользователем, но здесь это не так, и поэтому назначение перемещения по умолчанию не удаляется.
Существует также неявное преобразование из const char[12] в const char *, чтобы вызвать Person::Person(const char *)
@Peter: Да, это «бесплатное» преобразование.
Хитрость заключается в том, чтобы реализовать все 5 и записать, что происходит.