zoukankan      html  css  js  c++  java
  • 条款12:复制对象时勿忘其每一个成分

    设计良好的OO系统会将对象的内部封装起来,只留两个函数负责对象拷贝,那便是copy构造函数和copy assignment操作符。

             我们知道,如果不给类提供一个copy函数,则当需要时,编译器会为我们提供copy函数。

             但是,如果你自己声明了copy函数,就是在拒绝了编译器为你提供的版本。意思是你不喜欢编译器所提供的版本,此时,如果它好像是被冒犯了一样,如果你的代码出现了错误,它也不提醒你。

    classCustomer{

    ...

        Customer(constCustomer&rhs);

        Customer&operator=(constCustomer&rhs);

    ...

    private:

        std::stringname;    

    };

     

    Customer::Customer(constCustomer&rhs):name(rhs.name){ }

    Customer::operator=(constCustomer&rhs){

        name=rhs.name;

        return*this;

    }

    我们忽略第10条款所讲的内容,这是一个很好的程序,但是当我们的class发生变化时,灾难来了。比如我们的class加入一个新的数据成员:

    classDate{};

    classCustomer{

    ...

      Customer(constCustomer&rhs);

      Customer&operator=(constCustomer&rhs);

    ...

    private:

      std::stringname;    

      DatelastTransaction

    };

    而我们忽略了copy函数的修改,灾难就来了。因为,我们只对Customer对象的局部数据成员(name)进行了复制,而对lastTransaction成员没有操作,所以会使此数据成员未被初始化。

    classPriorityCustomer:publicCustomer{

    public:

      PriorityCustomer(constPriorityCustomer&rhs);

      PriorityCustomer&operator=(constPriorityCustomer&rhs);

    private:

      intpriority;

    };

     

    PriorityCustomer::PriorityCustomer(constPriorityCustomer&rhs):priority(rhs.priority){}

    PriorityCustomer&PriorityCustomer::operator=(constPriorityCustomer&rhs){

      this->priority=rhs.priority;

      return*this;

    }

    你会发现,此时的copy函数并没有对基类成员的初始化。因此隐式地会调用基类的无参的默认的构造函数,也就导致了基类局部成员的未初始化。为了避免此灾难,我们要显式的对基类成员进行初始化工作。

     

    PriorityCustomer::PriorityCustomer(constPriorityCustomer&rhs):priority(rhs.priority),Customer(rhs){}

    PriorityCustomer&PriorityCustomer::operator=(constPriorityCustomer&rhs){

        Customer::operator=(rhs);

        this->priority=rhs.priority;

        return*this;

    }

    因此,当你编写一个copy函数时,请确保:

    1)     复制所有的local成员变量

    2)     调用所有base classes内的适当的copying函数。

    注意以下两点:

    1)   令赋值操作符调用拷贝构造函数是不合理的。

    2)   令拷贝构造函数调用赋值操作符也是不合理的。

    如果你发现你的赋值操作符与拷贝构造函数有太多的相似代码,消除重复的方法是,建立一个新的成员函数供它们调用。这样的函数往往是private而且常命名为init。

    请记住:

    n   Copying函数应该确保复制“对象内的所有成员变量”及“所有base class 成员”

    n   不要尝试以某个copying函数实现另一个copying函数。应该将共同机能放进第三个函数中,并由两个copying函数共同调用。

  • 相关阅读:
    Debian/Kali下Subversion的配置
    Linux下解压Windows中的压缩包乱码解决办法
    JavaSocket全双工通信 问题 待解决
    MYSQL学习笔记
    Java Socket 全双工通信
    Kali2017安装后的那些事
    nginx的一次安装与配置
    解决1130 Host 'localhost' is not allowed to connect to this MySQL server
    SimpleDateFormat 和 LocalDate、LocalTime 以及时间大小比较简单示例
    java 线程池 ExeutorService
  • 原文地址:https://www.cnblogs.com/loveyakamoz/p/2772387.html
Copyright © 2011-2022 走看看