1. 试验功能:带有指针成员且指针成员为类类型时,自定义复制构造函数与赋值操作符的行为是怎样的。
2. 试验结果:
(1)当指针成员为一般普通成员时,我们可以自己在复制构造函数中为指针分配内存并拷贝内容,在赋值操作符函数中,检查或者删除左操作数的内存,并分配新内存然后拷贝内容到新分配内存中;
(2)当指针成员为类类型(本例即是)时,称为第一级类类型的指针成员:
在复制构造函数中:就要显式调用指针成员所属类型的复制构造函数生成一个临时对象,然后将该临时对象赋值给指针成员,可以通过两个方式进行赋值,一是:在复制构造函数的初始化式中以“指针变量(new 指针成员所属类类型复制构造函数)”的方式,二是:”指针变量=new 指针成员所属类类型复制构造函数“,本例方式为第一种方式,注意:这种方式显式调用了指针成员所属类的复制构造函数;
在赋值操作符函数中:可以直接用”对象=对象“的形式实现赋值操作符,如本例中:*pcd = *obj.pcd; pcd就是一个类类型的指针成员,注意这种赋值就会调用指针成员所属类的赋值操作符函数;
3. 当指针成员所属的类类型又包含指针成员时,仍然遵循本实验,即在一般指针成员时可以用(1)的方式实现拷贝,指针成员又为类类型时,就按照(2)的方式为该指针成员所属类实现复制构造函数和赋值操作符;这个指针成员所属类的复制构造函数和赋值操作符函数会在第一级指针成员所属类的复制构造函数和赋值操作符函数被调用的时候分别被调用,如果类类型指针成员所属类又包含了多级类类型的指针成员,就要为其做(2)的工作。
代码:
c.h 定义类 CC
//c.h defined class CC // #include "d.h" class CC { public: CC(); CC(int v1, int v2); virtual ~CC(); CC(const CC &obj); CC& operator=(const CC &obj); int getVal() const; int getObjVal() const; private: int a; CD *pcd; };c.cpp
#include "iostream" #include "c.h" CC::CC():a(0), pcd(new CD(0)) { std::cout << "CC Default constructor CC();" << std::endl; } CC::CC(int v1, int v2):a(v1), pcd(new CD(v2)) { std::cout << "CC constructor CC(int v1, intv2);" << std::endl; } CC::CC(const CC &obj):a(obj.a), pcd(new CD(*obj.pcd)) { std::cout << "CC Copy constructor CC(const CC &obj);" << std::endl; } CC &CC::operator=(const CC &obj) { std::cout << "CC assign constructor operator=(const CC &obj);" << std::endl; a = obj.a; *pcd = *obj.pcd; } CC::~CC() { std::cout << "CC DeConstructor ~CC();" << std::endl; delete pcd; } int CC::getVal() const { return a; } int CC::getObjVal() const { return pcd->getVal(); }d.h 定义类CD
//d.h defined class CD // class CD { public: CD() {}; CD(int v1):b(v1) {}; virtual ~CD() {}; CD(const CD &obj); CD &operator=(const CD& obj); int getVal() const; private: int b; };d.cpp
#include <iostream> #include "d.h" CD::CD(const CD &obj) { std::cout << "CD Copy constructor CD(const CD &obj);" << std::endl; b = obj.b; } CD &CD::operator=(const CD& obj) { std::cout << "CD assign constructor operator=(const CD &obj);" << std::endl; b = obj.b; } int CD::getVal() const { return b; }main.cpp
#include <iostream> #include "c.h" using namespace std; int test(CC o); int main() { CC c1(1, 10); CC c2(c1); cout << "c1.a:" << c1.getVal() << endl; cout << "c1.cd.b:" << c1.getObjVal() << endl; cout << "c2.a:" << c2.getVal() << endl; cout << "c2.cd.b:" << c2.getObjVal() << endl; cout << "test:" << test(c1) << endl; CC c3(3, 30); c3 = c2; cout << "c3.a:" << c3.getVal() << endl; cout << "c3.cd.b:" << c3.getObjVal() << endl; /* CD cd1; CD cd2; cd1 = cd2; */ return 0; } int test(CC o) { return o.getObjVal(); }
main 运行结果:
[root@centos cc++]# ./main
CC constructor CC(int v1, intv2);
CD Copy constructor CD(const CD &obj);
CC Copy constructor CC(const CC &obj);
c1.a:1
c1.cd.b:10
c2.a:1
c2.cd.b:10
CD Copy constructor CD(const CD &obj);
CC Copy constructor CC(const CC &obj);
test:10
CC DeConstructor ~CC();
CC constructor CC(int v1, intv2);
CC assign constructor operator=(const CC &obj); //CC包含类型为CD的指针成员pcd,当执行*pcd = *obj.pcd时,就会调用CC的赋值操作符,
CD assign constructor operator=(const CD &obj);//这时CD的赋值操作符就会被自动调用,因为这是对象赋值而不是指针赋值,指针赋值时,复制构造函数和赋值操作符就不会被自动调用,依次类推,如果CD又包含类类型的指针成员,那么我们也要为其实现复制构造函数和赋值操作符,那么他们也会被自动调用
c3.a:1
c3.cd.b:10
CC DeConstructor ~CC();
CC DeConstructor ~CC();
CC DeConstructor ~CC();