一、拷贝构造函数是一种特殊的构造函数,其形参为本类的对 象引用。
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默认为0Point 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;
}
运行结果如下: