1. 回顾构造函数
用代码分析
class Complex
{
private:
double Real;
double Image;
public:
Complex() :Real{}, Image{} //缺省的构造函数
{
cout << "Create Object() " << this << endl;
}
Complex(double r, double i) :Real{ r }, Image{ i }//带参数的构造函数
{
cout << "Create Object(double,double) " << this << endl;
}
~Complex()//析构函数,不带任何参数,无类型
{
cout << "Destroy Object " << this << endl;
}
void Print() const
{
cout << " Real= " << Real << " Image= " << Image << endl;
}
};
int main()
{
Complex ca;
ca.Print();
Complex cb(1.2, 2.3);
cb.Print();
return 0;
}
运行结果:
分析:从运行结果可以看出,进入主函数,运行Complex ca时,调用的是缺省的构造函数,运行Complex cb(1.2, 2.3)时,调用的是带参数的构造函数,然后调用析构函数,但是析构函数的调用首先是析构带参数的构造函数,最后析构缺省的构造函数。
那么,在主函数中,Complex cc(cb),这个程序会执行成功吗,这就有了拷贝函数的概念产生。
2. 拷贝构造函数
拷贝函数定义:同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制或称拷贝是完全可行的。这个拷贝过程只需要拷贝数据成员,而函数成员是共用的(只有一份拷贝)。在建立对象时可用同一类的另一个对象来初始化该对象的存储空间,这时所用的构造函数称为拷贝构造函数。
作用:
在程序运行时,如果一个对象去初始化另一个对象时,就得调用拷贝构造函数。
2.1 认识拷贝构造函数
示例:
class Complex
{
private:
double Real;
double Image;
public:
Complex() :Real{}, Image{} //缺省的构造函数
{
cout << "Create Object() " << this << endl;
}
Complex(double r, double i) :Real{ r }, Image{ i }//带参数的构造函数
{
cout << "Create Object(double,double) " << this << endl;
}
Complex(const Complex& com) :Real{com.Real}, Image{ com.Image }
{
cout << "Copy Create" << this << endl;
}
~Complex()//析构函数,不带任何参数,无类型
{
cout << "Destroy Object " << this << endl;
}
void Print() const
{
cout << " Real= " << Real << " Image= " << Image << endl;
}
};
int main()
{
Complex ca;
ca.Print();
Complex cb(1.2, 2.3);
cb.Print();
Complex cc(cb);
cc.Print();
return 0;
}
运行结果:
结果分析:从运行结果来看,在上述程序的基础上,添加了一个拷贝构造函数,拷贝构造函数的用法——是在程序运行中,一个对象去初始化另一个对象时,就得调用拷贝构造函数,调用析构函数时的顺序与构造函数时相反的。
2.2 实现缺省的拷贝构造函数
示例:
const int len = 20;
class CGoods
{
private:
char Name[len];
int Amount;
float Price;
float Total;
public:
CGoods() //缺省的构造函数
{
memset(Name, 0, sizeof(Name));
Amount = 0;
Price = 0.0;
Total = 0.0;
cout << "Create Object() " << this << endl;
}
CGoods(const char* name, int a, float p)//带参的构造函数
{
strcpy_s(Name, len, name);
Amount = a;
Price = p;
Total = Amount * Price;
cout << "Create Object(char,int,float) " << this << endl;
}
CGoods(const CGoods& cs)
{
strcpy_s(Name, len, cs.Name);
Amount = cs.Amount;
Price = cs.Price;
Total = cs.Total;
cout << "Copy Create" << this << endl;
}
~CGoods()//析构函数,不带任何参数,无类型
{
cout << "Destroy Object " << this << endl;
}
};
int main()
{
CGoods ca;
CGoods cb("biyadi", 10, 100000);
CGoods cd(cb);
return 0;
}
其中
运行结果:
从运行结果可以看出,用对象cb去初始化对象cd时,会调用拷贝构造函数。
2.3 类类型作为函数的形参
类类型作为函数的形参,有三种传递方式,值传递,引用传递,常引用传递,void funb(CGoods co),void func(CGoods &co),void fund(const CGoods& co),在我们传递我们的引用时,调用函数func,传递我们的引用不允许改变时,调用fund。
2.4 类类型作为函数的返回值
const int len = 20;
class CGoods
{
private:
char Name[len];
int Amount;
float Price;
float Total;
public:
CGoods() //缺省的构造函数
{
memset(Name, 0, sizeof(Name));
Amount = 0;
Price = 0.0;
Total = 0.0;
cout << "Create Object() " << this << endl;
}
CGoods(const char* name, int a, float p)//带参的构造函数
{
strcpy_s(Name, len, name);
Amount = a;
Price = p;
Total = Amount * Price;
cout << "Create Object(char,int,float) " << this << endl;
}
CGoods(const CGoods& cs)
{
strcpy_s(Name, len, cs.Name);
Amount = cs.Amount;
Price = cs.Price;
Total = cs.Total;
cout << "Copy Create" << this << endl;
}
~CGoods()//析构函数,不带任何参数,无类型
{
cout << "Destroy Object " << this << endl;
}
};
CGoods get()
{
CGoods dt("biyadi", 10, 100000);
return dt;
}
int main()
{
CGoods ca;
ca = get();
return 0;
}
运行结果:
分析结果:在程序运行时,进入主程序,首先调用的是缺省的构造函数,然后执行程序,到ca = get();,调用get函数,进入get函数后,CGoods dt(“biyadi”, 10, 100000);调用的是带参的构造函数,然后再调用拷贝构造函数,这在中间会产生一个将亡值,析构时候,先析构带参的构造函数,再析构拷贝构造函数,最后析构缺省的构造函数。
2.5 拷贝构造函数总结
拷贝构造函数的参数——采用引用,如果把一个真实的类对象作为参数传递到拷贝函数,会引起无穷递归,如
在类中如果没有显式给出拷贝函数时,则C++编译器自动给出一个缺省的拷贝构造函数,如果有程序设计者定义的构造函数(包括拷贝构造函数),则按函数重载的规律,调用合适的构造函数。
注意:缺省的拷贝构造函数特点:按位拷贝