Должен ли конструктор когда-либо вызываться при назначении?
Вывод кода, приведенного ниже в VS2015, является "конструктором".
Должен ли он не скомпилироваться из-за отсутствующего оператора присваивания?
struct A { };
struct B {
B(){}
B(const A& a) {
cout << "constructor" << endl;
}
//B& operator=(const A& a) {
// cout << "assignment operator" << endl;
// return *this;
//}
};
int main() {
A a;
B b;
b = a;
return 0;
}
Ответы
Ответ 1
Да, когда происходит конверсия, как в вашем тестовом файле.
Вы действительно называете
b = B(a);
Поскольку оператор присваивания B
B& operator=(B const&)
неявно объявлен, он обнаруживается при разрешении перегрузки. Поскольку ваше задание - это только одно преобразование от совпадения (и что именно количество преобразований, которое разрешено), оно преобразует a
в B
, а затем назначает новый временный B
на B
.
Ответ 2
Рассмотрим аналогичный пример.
double a;
int b=5;
a=b;
Единственное, что вы можете назначить double
, - это еще один double
. Однако int
можно преобразовать в double
.
Аналогично здесь A
можно преобразовать в B
, потому что существует такой конструктор. И что происходит.
Ответ 3
Ваш код имеет неявное преобразование от A
до B
, b = a
скомпилирован как b = B(a);
. Если вы хотите, чтобы это было обнаружено как ошибка, вы можете использовать спецификатор explicit
:
struct B {
B(){}
explicit B(const A& a) {
std::cout << "constructor" << std::endl;
}
};
Затем вы должны получить сообщение об ошибке, например сгенерированные ideone.com:
prog.cpp: In function 'int main()':
prog.cpp:20:7: error: no match for 'operator=' (operand types are 'B' and 'A')
b = a;
^
prog.cpp:5:8: note: candidate: B& B::operator=(const B&)
struct B {
^
prog.cpp:5:8: note: no known conversion for argument 1 from 'A' to 'const B&'
prog.cpp:5:8: note: candidate: B& B::operator=(B&&)
prog.cpp:5:8: note: no known conversion for argument 1 from 'A' to 'B&&'
После этого конструктор никогда не будет вызван неявным образом, и если вы хотите его называть, вы должны явно его написать: b = B(a);