简介
- 复制构造函数:就是构造函数的一种,只是形参是const类类型的引用。——— Sale_item(const Sale_item &orig)
//合成赋值操作符函数(下一节)
Sale_item& Sale_item::operator=(const Sale_item &rhs){//类外定义成员函数不要忘记加上类作用域Sale_item::
isbn=rhs.isbn;//逐个进行复制
units_sold=rhs.units_sold;
revenue=rhs.revenue;
return *this;//返回被赋值的那个对象
//赋值操作符函数函数名写法:"operator ="
//函数返回类型:类类型的引用Sale_item&
//形参:const 类类型的引用
}
//合成复制构造操函数
Sale_item::Sale_item(const Sale_item &orig):
isbn(orig.isbn),
units_sold(orig.units_sold),
revenue(orig.revenue)
{}
//因为是构造函数,所以函数名是类名,无返回值。因为是复制构造函数,所以形参是const类类型的引用,对里面的每个元素进行复制。
//这个函数是在类外定义,所以加上类作用域Sale_item::
//**(感觉和具有初始化列表的构造函数差不多,只是形参不同,这里的形参是const类类型的引用)**
用const类类型的引用做形参相当于是类的一个别名(想象一下const 普通类型的引用做形参)
但是有些类必须对复制对象时发生的事情加以控制。
- 这样的类经常有一个数据成员是指针;
- 或者有成员表示在构造函数中分配的其他资源。而另一些类在创建新对象时必须做一些特定工作。
这两种情况,都必须定义复制构造函数
但是有些类需要完全禁止复制。如iostream类就不允许复制。如果想要禁止复制,似乎可以省略复制构造函数,然而,如果不定义复制构造函数,编译器会默认合成一个。
为了防止复制,类必须显示声明其复制构造函数为private
-如果复制构造函数是私有的,将不允许用户代码复制该类类型的对象,编译器将拒绝任何进行复制的尝试。
- 然而,类的友元和成员仍然可以访问,即仍然可以复制,如果想要连友元和成员中的复制也禁止,就可以声明一个private复制构造函数但不对其定义。
=========================================================================================================================
一、合成构造函数
如果我们没有定义复制构造函数,编译器会为我们合成一个(默认的)。与合成的默认构造函数(12.4.1)不同,即使我们定义了其他构造函数,也会合成复制构造函数。合成复制构造函数是执行逐个成员初始化,将新对象初始化为原对象的副本。
所谓逐个成员指的是编译器将现有对象的每个非static成员,依次复制到正在创建的对象。只有一个例外,每个成员的类型决定了复制该成员的含义,合成复制构造函数直接复制内置类型成员的值,类类型成员使用该类的复制构造函数进行复制。数组成员的复制是个例外,虽然一般不能复制数组,但如果一个类具有数据成员,则合成复制构造函数将复制数组,复制数组合成构造函数将复制数组的每一个元素。
class Sale_item{
private:
std::string isbn;
int unit_sold;
double revenue;
};
//合成的复制构造函数
Sale_item::Sale_item(const Sale_item &orig):
isbn(orig.isbn),units_sold(orig.units_sold),revenue(orig.revenue)
{}
二、定义自己的复制构造函数
- 复制构造函数就是接受单个类类型引用形参(const)的构造函数
clss Foo{
public:
Foo();
Foo(const Foo&);//声明一个复制构造函数,首先是构造函数,所以名称和类名一样,再者形参必须是const的类类型的引用
};
- 无需显示定义复制构造函数。
但是有些类必须对复制对象时发生的事情加以控制。这样的类经常有一个数据成员是指针,或者有成员表示在构造函数中分配的其他资源。而另一些类在创建新对象时必须做一些特定工作。这两种情况,都必须定义复制构造函数
认识到什么情况下需要定义复制构造函数是困难的。复制构造函数也是构造函数,所以,没有返回值,名称与类名相同,可以(而且应)使用构造函数初始化列表初始化新创建对象的成员,可以在函数体中做任何其他必要工作。
三、禁止复制
有些类需要完全禁止复制。如iostream类就不允许复制。如果想要禁止复制,似乎可以省略复制构造函数,然而,如果不定义复制构造函数,编译器会默认合成一个。
为了防止复制,类必须显示声明其复制构造函数为private
-如果复制构造函数是私有的,将不允许用户代码复制该类类型的对象,编译器将拒绝任何进行复制的尝试。
- 然而,类的友元和成员仍然可以访问,即仍然可以复制,如果想要连友元和成员中的复制也禁止,就可以声明一个private复制构造函数但不对其定义。
- 声明而不定义成员函数是合法的,但是,使用未定义成员的任何尝试将导致链接失败。通过声明但不定义private复制构造函数,可以禁止任何复制类类型对象的尝试。