zoukankan      html  css  js  c++  java
  • 复制控制( 上 ) --- 自定义复制函数

    前言

      若要将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引用且无返回 )

  • 相关阅读:
    【EmguCv】人脸/人眼检测
    iOS 9下Universal Link(通用链接)开发
    【JavaWeb】SpringMvc返回json
    【nlp】湖北师范大学贴吧帖子标题词频统计
    【C#】EAN-13条形码生成与识别
    【C#】身份证识别(三):身份证信息识别
    【C#】身份证识别(二):提取目标区域图像
    米勒罗宾素性测试算法简介+模板(转)
    CodeForces
    CodeForces
  • 原文地址:https://www.cnblogs.com/scut-fm/p/3239489.html
Copyright © 2011-2022 走看看