值的赋值运算符未使用显式复制构造函数进行编译

assignment operator by value not compiling with explicit copy constructor

本文关键字:构造函数 编译 复制 赋值运算符 未使用      更新时间:2023-10-16

我想了解在显式复制构造函数中应该使用哪些正确的参数类型。

如下所定义,使用"显式",赋值代码将不会编译。main中的赋值行生成错误:"没有用于初始化CCat的匹配构造函数"

从第一个副本构造函数中删除"显式"可以解决这个问题,但我不明白为什么。

编译器显然在做一些微妙的隐式转换?

class CCat : public CAnimal
{
public:
    explicit CCat( string name, uint noLegs, bool fur, bool domestic, string breed );
    explicit CCat( const CCat& oldCat ) : CAnimal( oldCat )
    {
        std::cout << "nCCat::CCat( const CCat& oldCat ) n";
    }
    explicit CCat( CCat& oldCat ) : CAnimal( oldCat )
    {
        std::cout << "nexplicit CCat::CCat( CCat& oldCat ) n";
    }
    ~CCat();
    CCat& operator =( CCat oldCat ){
        //.. do assignment stuff
        return *this;
    }
};
int main(int argc, const char * argv[])
{
    CCat *cat1 = new CCat( string("Wiggy"),  4, true, true, string("Tabby") );
    CCat *cat2 = new CCat( string("Tibles"),  4, true, true, string("Tom") );
    CCat tempCat( *cat1 );
    CCat tempCat2( *cat2 );
    std::cout << "CCat tempCat2( *cat2 );n";
    const CCat& tempCat3 = *cat2;
    tempCat = tempCat3;    // will not compile without explicit removed from first C/Constr
    tempCat = CCat(*cat2); // will not compile without explicit removed from first C/Constr
    tempCat = tempCat2;    // will not compile without explicit removed from first C/Constr
    return 0;
}

赋值运算符(传递值)强制使用复制构造函数,但是使用显式时无法找到完全匹配。那么,当显式被删除时,编译器正在执行什么转换?我如何编写匹配的复制构造函数?

分配

tempCat = tempCat3

通过过载分辨率进行调查,并重写为

tempCat.operator=(tempCat3)

重载解析现在查找要调用的匹配成员函数。它会找到您的副本分配操作员:

CCat& operator=( CCat oldCat )

参数oldCat必须使用参数tempCat3进行初始化。正确的术语实际上是复制初始化

以形式发生的初始化

T x = b;

在参数传递中,[…]被称为复制初始化

复制初始化仅适用于非显式构造函数:

对于副本初始化,候选函数是转换该类的构造函数(12.3.1)。

(也称为转换构造函数):

声明的构造函数没有函数说明符explicit指定从其参数类型到的类型的转换它的类别。这样的构造函数被称为转换构造函数

因此,如果你用const-引用参数将复制构造函数声明为explicit,它就不是转换构造函数,复制初始化不起作用,参数也不能用参数初始化-这也是编译器告诉我们的,找不到匹配的构造函数
main中的其他行也是如此。

如果删除了explicit,则初始化工作正常。