c++中拷貝構造函數&賦值操做符的理解

18/2/6 將具體例子改成Ch09_Point類(做爲指針變量使用),Ch09_CopyConstructor類(做爲父類,包含Ch09_Point指針變量),Ch09_DeprivedClass類(做爲子類)。經過這三個類的相互關係,介紹c++的拷貝構造函數和賦值操做符的使用。c++

拷貝構造函數(copy constructor)又稱爲複製構造函數,此函數常常用在函數調用時用戶自定義類型的值傳遞及返回。若是沒有定義拷貝構造函數,編譯器會自動爲咱們建立一個,拷貝構造函數會逐個執行成員的初始化(按照類成員在類中聲明的順序)。對於基本類型數據默認拷貝構造函數能夠正常建立一個副本並由被賦值對象持有;對於類類型數據直接調用數據的拷貝構造函數建立新的副本並由被賦值對象持有(有可能兩個對象共同持有一個數據);對於指針類數據,默認拷貝函數會讓兩個對象共同持有一個數據,致使修改A對象,B對象的值跟着變化,在程序中形成異常。函數

拷貝構造函數調用條件:this

1)一個對象最爲函數參數,以「值傳遞」的方式傳入函數體。指針

2)一個對象做爲函數返回值,以「值傳遞」的方式從函數返回。code

3)一個對象對另外一個對象進行初始化。對象

拷貝構造函數及賦值操做符(C++建議類的賦值操做符做爲類方法出現,一樣建議的還有「.」, "[]", "()")格式:ci

Ch09_Point.h:

class Ch09_Point
{
public:
    explicit Ch09_Point();
    explicit Ch09_Point(int x, int y);

    /**
     *@author        qioawei
     *@date          2018-02-05
     *@version       1.0
     *@brief         拷貝構造函數
     *@called by
     *@param         p
     **/
    Ch09_Point(const Ch09_Point& p);

    void print() const;

    void SetPoint(int x, int y);

    int GetX() const;

    int GetY() const;

    /**
     *@author        qioawei
     *@date          2018-02-05
     *@version       1.0
     *@brief         = 賦值操做符
     *@called by
     *@param         rvalue 賦值變量
     *@return        賦值後
     **/
    Ch09_Point& operator = (const Ch09_Point& rvale);

    friend Ch09_Point operator + (const Ch09_Point& a, const Ch09_Point& b);

private:
    int x_;
    int y_;
};

Ch09_Point.cpp:

#include "ch09_point.h"

Ch09_Point::Ch09_Point() :
    x_(0),
    y_(0)
{

}

Ch09_Point::Ch09_Point(int x, int y) :
    x_(x),
    y_(y)
{

}

Ch09_Point::Ch09_Point(const Ch09_Point &p)
{
    x_ = p.x_;
    y_ = p.y_;
}

void Ch09_Point::print() const
{
    qDebug() << "x = " << x_ << ", y = " << y_ << endl;
}

void Ch09_Point::SetPoint(int x, int y)
{
    x_ = x;
    y_ = y;
}

int Ch09_Point::GetX() const
{
    return x_;
}

int Ch09_Point::GetY() const
{
    return y_;
}

Ch09_Point& Ch09_Point::operator = (const Ch09_Point &rvale)
{
    if (this != &rvale) {
        x_ = rvale.x_;
        y_ = rvale.y_;
    }

    return *this;
}

Ch09_Point operator + (const Ch09_Point &a, const Ch09_Point &b)
{
    return Ch09_Point(a.x_ + b.x_, a.y_ + b.y_);
}

使用狀況:編譯器

Ch09_Point a1; //調用無參構造函數
Ch09_Point a2(a1); //調用拷貝構造函數
Ch09_Point a3 = a1; //調用拷貝構造函數
Ch09_Point a4;
a4 = a2 //賦值操做符

//特殊狀況
Ch09_Point* a5(new A());
Ch09_Point  a6(*a5) //調用拷貝構造函數
Ch09_Point* p3 = new Ch09_Point(10, 20);   //構造函數
a6 = *p3; //賦值操做符
Ch09_Point p4(*p3);   //拷貝構造函數

「=」在對象聲明語句中表示初始化,調用拷貝構造函數;在非聲明語句中表示賦值,調用賦值構造函數。it

 

Ch09_CopyConstructor類做爲容器類,保存Ch09_Point類型指針,具體以下:io

ch09_copyconstructor.h

class Ch09_Point;

class Ch09_CopyConstructor
{
public:
    explicit Ch09_CopyConstructor();
    explicit Ch09_CopyConstructor(int x, int y);

    /**
     *@author        qioawei
     *@date          2018-02-05
     *@version       1.0
     *@brief         拷貝構造函數
     *@called by
     *@param         cc
     **/
    Ch09_CopyConstructor(const Ch09_CopyConstructor& cc);

    ~Ch09_CopyConstructor();

    Ch09_CopyConstructor& operator = (const Ch09_CopyConstructor& rvalue);

    void Print() const;

private:
    Ch09_Point* p_;
};

ch09_copyconstructor.cpp

#include "ch09_copyconstructor.h"

#include "ch09_point.h"

Ch09_CopyConstructor::Ch09_CopyConstructor() :
    p_(new Ch09_Point(0, 0))
{

}

Ch09_CopyConstructor::Ch09_CopyConstructor(int x, int y) :
    p_(new Ch09_Point(x, y))
{
}

Ch09_CopyConstructor::Ch09_CopyConstructor(const Ch09_CopyConstructor &cc)
{
    if (this != &cc) {
        delete p_;

        //調用Ch09_Point的拷貝構造函數
        p_ = new Ch09_Point(*(cc.p_));
    }
}

Ch09_CopyConstructor::~Ch09_CopyConstructor()
{
    delete p_;

    //qDebug() << "from base class" << endl;
}

Ch09_CopyConstructor& Ch09_CopyConstructor::operator =(const Ch09_CopyConstructor& rvalue)
{
    if (this != &rvalue) {
        delete p_;
        //調用Ch09_Point拷貝構造函數?
        p_ = new Ch09_Point(*(rvalue.p_));
    }

    return *this;
}

void Ch09_CopyConstructor::Print() const
{
    p_->print();
}

由於p_變量在構造函數中進行初始化,在進行拷貝構造或者賦值操做時須要先判斷,如與所賦對象不一致,則須要先delete p_的實例,隨後建立新實例保存所賦對象中數據。

 

Ch09_DeprivedClass類做爲Ch09_CopyConstructor的子類,同時在Ch09_DeprivedClass類中保存一個Ch09_Point類做爲變量保存。

Ch09_DeprivedClass.h

class Ch09_Point;

class Ch09_DeprivedClass : public Ch09_CopyConstructor
{
public:
    explicit Ch09_DeprivedClass();
    explicit Ch09_DeprivedClass(int x, int y);

    Ch09_DeprivedClass(const Ch09_DeprivedClass& dc);

    virtual ~Ch09_DeprivedClass();

    Ch09_DeprivedClass& operator =(const Ch09_DeprivedClass& dc);

    void PrintDeprivedClass();

public:
    Ch09_Point* deprived_p_;
};

Ch09_DeprivedClass.cpp

#include "ch09_deprivedclass.h"

#include "ch09_point.h"

Ch09_DeprivedClass::Ch09_DeprivedClass() :
    Ch09_CopyConstructor(),
    deprived_p_(new Ch09_Point(0, 0))
{
    qDebug() << deprived_p_ << endl;
}

Ch09_DeprivedClass::Ch09_DeprivedClass(int x, int y) :
   Ch09_CopyConstructor(x, y),
   deprived_p_(new Ch09_Point(x + 11, y + 22))
{
    qDebug() << deprived_p_ << endl;
}

Ch09_DeprivedClass::Ch09_DeprivedClass(const Ch09_DeprivedClass &dc) :
    Ch09_CopyConstructor(dc)        //調用基類拷貝構造函數
{
    if (this != &dc) {
        delete deprived_p_;

        deprived_p_ = new Ch09_Point(*(dc.deprived_p_));
        //deprived_p_ = new Ch09_Point(dc.deprived_p_->GetX(), dc.deprived_p_->GetY());
    }
}

Ch09_DeprivedClass::~Ch09_DeprivedClass()
{
    delete deprived_p_;

    //qDebug() << "from deprived class" << endl;
}

Ch09_DeprivedClass &Ch09_DeprivedClass::operator =(const Ch09_DeprivedClass &dc)
{
    if (this != &dc) {
        delete this;

        //調用基類賦值操做符,完成基類private變量的賦值
        Ch09_CopyConstructor::operator =(dc);
        deprived_p_ = new Ch09_Point(*(dc.deprived_p_));
    }

    return *this;
}

void Ch09_DeprivedClass::PrintDeprivedClass()
{
    Print();

    qDebug() << " deprived x = " << deprived_p_->GetX()
             << ", deprived y = " << deprived_p_->GetY() << endl;
}

在拷貝構造函數中須要調用基類的拷貝構造函數;在賦值操做符中調用基類賦值操做符,給基類中保存的private變量賦值。

相關文章
相關標籤/搜索