首页 > 代码库 > 第十七篇:复制控制( 上 ) --- 自定义复制函数

第十七篇:复制控制( 上 ) --- 自定义复制函数

前言

  若要将a对象复制给b对象,编译器应当做何工作?C++初学者也许会直接说” a对象的成员复制给b对象的成员 “。在很多情况下,这种说法正确,事实上C++会给类定义一个默认的复制函数,它所做的工作也正是如此。但,下面问题来了:如果类的成员当中有指针,这种做法还行吗?本文将对这个问题作出实例分析。

一个典型错误示例

  下面这个代码示例用来检验前言中所提到的问题:

 1 #include <iostream> 2 #include <cstdlib> 3 #include <fstream> 4 #include <string> 5  6 using namespace std; 7  8 class A { 9 public:10     // 构造函数为指针成员开辟空间并赋初值011     A() {12         num_p = new int;13         *num_p = 0;14     }15     // 给指针所指对象赋值16     void setNum(int num) {17         *num_p = num;18     }    19     // 获取指针所指对象20     int getNum() const {21         int num = *num_p;22         return num;23     }24 private:25     int *num_p;26 };27 28 int main()29 {30     A a1;31 32     // 设置a1指针成员所指对象的值33     a1.setNum(1);34     // 调用系统自动合成的复制函数35     A a2 = a1;36     // 观察得出a1,a2的指针成员所指对象均为整数1。37     cout << "a1`s num: " << a1.getNum() << endl;38     cout << "a2`s num: " << a2.getNum() << endl;39 40     // 修改a1指针成员所指对象的值41     a1.setNum(2);42     // 观察得出不单a1的指针成员所指对象改了,a2的也跟着变了。 43     cout << "a1`s num: " << a1.getNum() << endl; 44     cout << "a2`s num: " << a2.getNum() << endl;45 46     return 0;47 }

       运行结果:

       技术分享

       我们可以观察到,当类中具有指针成员时,如果使用默认的复制函数,那么此后当某个对象修改了其指针成员所指对象,那么该类派生的其他对象的指针成员所指对象也会跟着改变。这显然不符合编程规范,下面我们将提出解决方案。

解决思路

       既然系统自带的复制函数无法满足我们的要求,那么我们可以自定义一个以指定编译器在复制对象时的操作。

一个正确示例

       下面这个代码给出了一个具体解决方案,复制函数启用时,拷贝指针所指对象,而不是指针本身:

 1 #include <iostream> 2 #include <cstdlib> 3 #include <fstream> 4 #include <string> 5  6 using namespace std; 7  8 class A { 9 public:10     // 构造函数为指针成员开辟空间并赋初值011     A() {12         num_p = new int;13         *num_p = 0;14     }15     // 自定义复制函数 16     A(const A & a) {17         num_p = new int;18         *num_p = a.getNum();19     }20     // 给指针所指对象赋值21     void setNum(int num) {22         *num_p = num;23     }    24     // 获取指针所指对象25     int getNum() const {26         int num = *num_p;27         return num;28     }29 private:30     int *num_p;31 };32 33 int main()34 {35     A a1;36 37     // 设置a1指针成员所指对象的值38     a1.setNum(1);39     // 调用自定义的复制函数40     A a2=a1;41     // 观察得出a1,a2的指针成员所指对象均为整数1。42     cout << "a1`s num: " << a1.getNum() << endl;43     cout << "a2`s num: " << a2.getNum() << endl;44 45     // 修改a1指针成员所指对象的值46     a1.setNum(2);47     // 观察得出a1的指针成员所指对象改了,a2的没变。 48     cout << "a1`s num: " << a1.getNum() << endl; 49     cout << "a2`s num: " << a2.getNum() << endl;50 51     return 0;52 }

       运行结果:

       技术分享

       这一次,两个对象没有出现“ 相互干扰 ”了。

说明

       1. 复制函数不单在A a = b的形式下启用,在作为函数参数传递时,生成容器时也会启用,这点要注意到。

       2. 注意复制函数的原型( 形参为const引用且无返回 )

第十七篇:复制控制( 上 ) --- 自定义复制函数