我无法理解为什么调用拷贝构造函数而不是编译错误的原因。
我声明了两个A B类,它们是独立的。 A不是基于/派生于B。它们之间的唯一联系是在B中,我使用了将B转换为A的运算符 我已经定义了一个操作符=,它将B的const引用作为参数。 总的来说,我写了下面的B = A实例的实例。我希望会产生编译错误。但是运算符=称为
class A {};
class B {
public:
// conversion from A (constructor):
B()
{
cout << "1." << endl;
}
B(const A& x)
{
cout << "4." << endl;
}
// conversion from A (assignment):
B& operator= (const B& x)
{
cout << "3." << endl;
return *this;
}
// conversion to A (type-cast operator)
operator A() {
cout << "2." << endl;
return A();
}
};
int main()
{
A foo;
B bar; // calls constructor
bar = foo; // calls assignment
//foo = bar; // calls type-cast operator
char c;
c = getchar();
return 0;
}
我期望编译错误。但是打印以下顺序 1 4 3。 我几乎无法理解复制构造函数的调用方式以及为什么operator =不会产生问题
谢谢
答案 0 :(得分:3)
这不是您拥有的复制构造函数,而是转换构造函数。之所以调用转换构造函数,是因为您可以将A
转换为B
。
执行以下操作:
explicit B(const A& x)
现在您将禁止从A
到B
的隐式转换。
当您这样做:
bar = foo;
编译器寻找合理的操作,最多允许一次转换。它可以使用来自B
的副本分配,并且知道可以从B
中创建一个A
(因为构造函数不是显式的),因此它会静默地执行此操作。>
正如@lubgr所说,clang-tidy有一个规则来检查这些,这就是part of the C++ core guidelines。
答案 1 :(得分:3)
您有一个隐式构造函数
list-style-position:outside
执行不需要的转换。您可以将签名更改为
B::B(const A&)
触发编译错误。请注意,优良作法是在默认情况下用一个参数explicit B(const A&);
标记构造函数(也有一个explicit
check),只是为了避免偶然地进行此类转换(恕我直言,如果可以使用单个参数构造的构造函数默认情况下为clang-tidy
并且具有隐式的功能,那就更好了。
答案 2 :(得分:2)
我希望会生成以下编译错误
no match for 'operator=' ... note: no known conversion for argument 1 from 'A' to 'const B&'
没有理由预料到这种错误,因为已知有一个从A
到const B&
的转换。 B
具有A
的转换构造函数:
B(const A& x)
它们之间的唯一联系是在B中,我使用了将B转换为A的运算符
...,它们之间的第二个联系是在B
中,您使用了一个将A
转换为B
的构造函数。
您是正确的,这是一个转换指导员。但是为什么在分配bar = foo发生时调用此方法。
因为赋值的给定操作数的类型为A
,而声明的参数类型为const B&
。
在参数类型与声明不匹配的情况下,编译器将检查是否存在可用于转换参数的隐式转换序列。由于A
可以隐式转换为B
,所以这种隐式转换序列存在并将被使用。