码迷,mamicode.com
首页 > 其他好文 > 详细

当自己编写copying函数的时候要负责手动将每一个成员都拷贝

时间:2015-05-30 07:01:25      阅读:311      评论:0      收藏:0      [点我收藏+]

标签:

结论1:如果自己编写copying函数则编译器就不会再为你自动生成,如果新追加一个成员变量,但是忘记在copying函数中追加这个变量的拷贝行为,这样编译器不会提示任何错误和警告信息,但是新变量不会被拷贝。因此如果追加新的成员变量,必须记住手动为该成员变量实现copying操作。

代码段1.1:Customer.h文件

技术分享
#ifndef CUSTOMER_H
#define CUSTOMER_H

#include <string>
#include "Date.h"

class CCustomer
{
public:
    CCustomer(int month = 1, int day = 1, std::string name = "" ):m_name(name)
    {
        m_date.Setmonth(month);
        m_date.Setday(day);
    }
    CCustomer(const CCustomer& rhs);
    CCustomer& operator= (const CCustomer& rhs);
private:
    std::string m_name;
    CDate m_date;  //新加的就必须手动补上copying动作
    void logCall(const std::string& funcName);
};

#endif
View Code

代码段1.2:Customer.cpp文件

技术分享
#include "Customer.h"
#include <iostream>

CCustomer::CCustomer(const CCustomer& rhs):m_name(rhs.m_name)/*,m_date(rhs.m_date) */ //此处加深理解,任何对象的private成员都可在本类中访问(为什么?作为下个课题)
{
    logCall("copy construct function");   //构造函数中也可以任意使用类的成员函数,不必是静态函数(为什么?作为下个课题)
}

CCustomer& CCustomer::operator=(const CCustomer& rhs)
{
    logCall("equal operator");
    m_name = rhs.m_name;
    /*m_date = rhs.m_date;*/
    return *this;
}

void CCustomer::logCall(const std::string& funcName)
{
    std::cout<<funcName<<std::endl;
}
View Code
代码段1.3:Date.h文件
技术分享
#ifndef DATE_H
#define DATE_H

class CDate
{
public:
    CDate(int month = 1, int day = 1):m_month(month),m_day(day){}
    void Setmonth(int month){m_month = month;}
    void Setday(int day){m_day = day;}
private:
    int m_month;
    int m_day;
};

#endif
View Code

代码段1.4:main.cpp文件

技术分享
#include "Customer.h"

int main()
{
    CCustomer c1(8,1,"lsy");
    CCustomer c2(c1);  //不会提示任何编译错误或警告,但是新追加的成员变量没有被复制
    CCustomer c3;
    c3 = c1;  //同上
    return 0;
}
View Code

结论2:如果一个类继承另一个类,编写copying函数时如果只copy了子类的成员变量而忽略了父类的成员变量,那么父类的成员变量不会被copy(因为copy构造函数也是一种构造函数,如果不手动写父类成员变量的拷贝,则copy构造函数会调用父类成员的默认构造函数等获取父类成员变量的默认值,赋值操作符也不会调用父类的赋值操作符。而只有编译器生成的copy构造函数和赋值操作符才调用父类的copy构造函数和赋值操作符),这时如果要让父类的成员变量实现copy,那么必须手动调用父类的拷贝构造函数和赋值运算符实现copying。

代码段2.1:PriorityCustomer.h文件

技术分享
#ifndef PRIORITYCUSTOMER_H
#define PRIORITYCUSTOMER_H

#include "Customer.h"

class CPriorityCustomer:public CCustomer
{
public:
    CPriorityCustomer(int priority = 0, int month = 1, int day = 1, std::string name = ""): CCustomer(month,day,name),m_priority(priority){}
    CPriorityCustomer(const CPriorityCustomer& rhs);
    CPriorityCustomer& operator=(const CPriorityCustomer& rhs);
private:
    int m_priority;
};

#endif
View Code

代码段2.2:PriorityCustomer.cpp文件

技术分享
#include "PriorityCustomer.h"

CPriorityCustomer::CPriorityCustomer(const CPriorityCustomer& rhs):m_priority(rhs.m_priority)/*,CCustomer(rhs)*/
{
    logCall("PriorityCustomer copy constructor");
}

CPriorityCustomer& CPriorityCustomer::operator=(const CPriorityCustomer& rhs)
{
    logCall("PriorityCustomer equal operator");
    m_priority = rhs.m_priority;
    /*CCustomer::operator=(rhs);*/
    return *this;
}
View Code

代码段2.3:main.cpp文件

技术分享
#include "Customer.h"
#include "PriorityCustomer.h"

int main()
{
    //CCustomer c1(8,1,"lsy");
    //CCustomer c2(c1);  //不会提示任何编译错误或警告,但是新追加的成员变量没有被复制
    //CCustomer c3;
    //c3 = c1;  //同上

    CPriorityCustomer c1(2,8,1,"lsy");
    CPriorityCustomer c2(c1);
    CPriorityCustomer c3;
    c3 = c1;

    return 0;
}
View Code

结论3:虽然copy构造函数和赋值运算符代码相似,但是为了复用代码而互相调用是不可以的,因为copy构造函数是构造一个对象,赋值运算符是为一个对象赋值,二者截然不同,如果为了复用代码,可以将二者的共性抽出放到一个private成员函数中管理。

当自己编写copying函数的时候要负责手动将每一个成员都拷贝

标签:

原文地址:http://www.cnblogs.com/lisiyuannnn/p/4539704.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!