• 复制控制( 上 ) --- 自定义复制函数


    前言

      若要将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     // 构造函数为指针成员开辟空间并赋初值0
    11     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     // 构造函数为指针成员开辟空间并赋初值0
    11     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引用且无返回 )

  • 相关阅读:
    linux命令--cp
    linux命令--mv
    CSS属性值定义语法中的符号说名
    select选项改变时获取选中的option的值
    JS截取字符串:slice(),substring()和substr()
    正则表达式进行密码验证
    利用@media实现IE hack
    javascript版1024游戏源码
    canvas写的一个小时钟demo
    gl.vertexAtteib3f P42 讲数据传给location参数指定的attribute变量
  • 原文地址:https://www.cnblogs.com/scut-fm/p/3239489.html
Copyright © 2020-2023  润新知