Bootstrap

拷贝(复制)构造函数定义及3种调用情况举例

一、拷贝构造函数是一种特殊的构造函数,其形参为本类的对 象引用。

class 类名 

{ public : 类名(形参);//构造函数

                类名(类名 &对象名);//拷贝构造函数 ... 
};

//拷贝构造函数 ... 

类名::类(类名 &对象名)//拷贝构造函数的实现

{ 函数体 }

如:

Box∷Box(const Box& b)

{

height=b.height;

width=b.width;

length=b.length;

}

复制构造函数也是构造函数,但它只有一个参数,这个参数是本类 的对象(不能是其他类的对象),而且采用对象的引用的形式(一般约定 加const声明,使参数值不能改变,以免在调用此函数时因不慎而使对 象值被修改)。 如果用户自己未定义复制构造函数,则编译系统会自动提供一个默认的 复制构造函数,其作用只是简单地复制类中每个数据成员。

二、请注意普通构造函数和复制构造函数的区别

(1) 在形式上

类名(形参表列); //普通构造函数的声明,如Box(int h,int ,int en);

类名(类名& 对象名); //复制构造函数的声明,如Box(Box &b);

(2) 在建立对象时,实参类型不同

系统会根据实参的类型决定调用普通构造函数或复制构造函数。

如 Box box1(12,15,16); //实参为整数,调用普通构造函数

Box box2(box1); //实参是对象名,调用复制构造函数

(3) 在什么情况下被调用

普通构造函数在程序中建立对象时被调用。 复制构造函数在用已有对象复制一个新对象时被调用,在以下3 种情况下需要克隆对象:

① 程序中需要新建立一个对象,并用另一个同类的对象对它初始化:

box2=box1//box2(box1)

② 当函数的参数为类的对象时。在调用函数时需要将实参对象 完整地传递给形参,也就是需要建立一个实参的拷贝,这 就是按实参复制一个形参,系统是通过调用复制构造函数 来实现的,这样能保证形参具有和实参完全相同的值。如

void fun(Box b) //形参是类的对象

{  }

int main( )

{Box box1(12,15,18);

fun(box1); //实参是类的对象,调用函数时将复制一个新对象b

return 0;

}

③ 函数的返回值是类的对象。 在函数调用完毕将返回值带回函数调用处时。此时需要将函数中的对象 复制一个临时对象并传给该函数的调用处。如:

Box f( ) //函数f的类型为Box类类型

{ Box box1(12,15,18);

return box1; //返回值是Box类的对象

}

int main( )

{Box box2; //定义Box类的对象box2

box2=f( ); //调用f函数,返回Box类的临时对象,并将它赋值给box2

}

以上几种调用复制构造函数都是由编译系统自动实现的,不必由用户自 己去调用,只要知道在这些情况下需要调用复制构造函数就可以了。

三、调用拷贝构造函数的例子(Point类为例)

#include "iostream"
using namespace std;

//定义一个Point类
class Point{
public:
	Point(int xx=0,int yy=0):x(xx),y(yy){}     //构造函数
	~Point(){ };                              //析构函数
    Point(const Point &p);                //复制构造函数
	int getX()const{return x;}
	int getY()const {return y;}
private:
	int x,y;//私有成员

};

Point::Point(const Point &p)
{
	x = p.x;
	y = p.y;
	cout << "Calling the copy constructor" <<endl;

}
//形参作为Point类对象的函数
void fun1(Point p)
{
	cout<< p.getX()<<endl;

}

//返回类的对象
Point fun2()
{
	Point a(1,2);
	return a;
}

int main()
{
	Point a(4);    //第一个对象A,该过程利用了重载,后面的y默认为0
	
	Point b(a);      //此时调用copy构造函数;情况1,用a初始化b,第一次调用copy构造函数
	cout << b.getX()<<endl; 

	fun1(b);  //此时调用copy构造函数;类的对象在函数中为实参,第二次调用copy构造函数

	b = fun2();//此时调用copy构造函数;函数返回值为类的对象,第三次调用copy构造函数
	cout << b.getX()<<endl; 
	return 0;
}

运行结果如下:

 

;