我有以下课程,其中一些操作符被重载:
class CLASS1
{
CLASS1();
CLASS1(const CLASS1 &obj);
CLASS1 operator +(const CLASS1 &obj) {
CLASS1 srcObj;
// doing add stuff here
return srcObj;
}
void func()
{
CLASS1 boj = // some method which returns CLASS1 obj.
}
CLASS1& operator =(const CLASS1 &obj) {
// copy properties
}
}
好的,这很好用。但过了一段时间后,我决定让我的课明确,以避免隐式转换。因此,我已经这样做了:
class CLASS1
{
explicit CLASS1();
explicit CLASS1(const CLASS1 &obj);
CLASS1 operator +(const CLASS1 &obj) {
CLASS1 srcObj;
// doing add stuff here
return srcObj; // compiler gives non-matching errors
}
void func() {
CLASS1 boj = somemethods(); // compiler gives non-matching errors
}
CLASS1& operator =(const CLASS1 &obj) {
// copy properties
}
}
现在,编译器给出了“没有匹配函数来调用...”错误(在上面的代码中指定),尽管我明确地重载了赋值运算符。我的错误在哪里?
答案 0 :(得分:2)
按值返回对象时,复制构造函数将隐式调用 。如果你说不允许隐式调用,你会收到错误。
您不应将explicit
用于默认,复制或移动构造函数。或者对于构造函数采取多个参数。仅适用于采用单个参数的构造函数(具有注明的例外)。
答案 1 :(得分:1)
从技术上讲,从方法返回对象时,在方法调用之外接收的对象实际上是在方法内声明的对象的副本。所以编译器必须有一个允许的方式来传输内容"从in-method对象到方法结果。由于不再需要in-method实例,因此移动是最佳方法(是的,您需要添加移动构造函数):
CLASS1(CLASS1&& obj);
这将允许您禁止隐式转换,同时保持具有临时对象的能力。
在现实生活中,可能会被RVO / NRVO优化出来的副本/移动。