zoukankan      html  css  js  c++  java
  • c++中拷贝构造函数&赋值操作符的理解

    20180206修订:将具体例子改为Ch09_Point类(作为指针变量使用),Ch09_CopyConstructor类(作为父类,包含Ch09_Point指针变量),Ch09_DeprivedClass类(作为子类)。通过这三个类的相互关系,介绍c++的拷贝构造函数和赋值操作符的使用。

    拷贝构造函数(copy constructor)又称为复制构造函数,此函数经常用在函数调用时用户自定义类型的值传递及返回。如果没有定义拷贝构造函数,编译器会自动为我们创建一个,拷贝构造函数会逐个执行成员的初始化(按照类成员在类中声明的顺序)。对于基本类型数据默认拷贝构造函数可以正常创建一个副本并由被赋值对象持有;对于类类型数据直接调用数据的拷贝构造函数创建新的副本并由被赋值对象持有(有可能两个对象共同持有一个数据);对于指针类数据,默认拷贝函数会让两个对象共同持有一个数据,导致修改A对象,B对象的值跟着变化,在程序中造成异常。

    拷贝构造函数调用条件:

    1)一个对象最为函数参数,以“值传递”的方式传入函数体。

    2)一个对象作为函数返回值,以“值传递”的方式从函数返回。

    3)一个对象对另一个对象进行初始化。

    拷贝构造函数及赋值操作符(C++建议类的赋值操作符作为类方法出现,同样建议的还有“.”, "[]", "()")格式:

      1 Ch09_Point.h:
      2 
      3 class Ch09_Point
      4 {
      5 public:
      6     explicit Ch09_Point();
      7     explicit Ch09_Point(int x, int y);
      8 
      9     /**
     10      *@author        qioawei
     11      *@date          2018-02-05
     12      *@version       1.0
     13      *@brief         拷贝构造函数
     14      *@called by
     15      *@param         p
     16      **/
     17     Ch09_Point(const Ch09_Point& p);
     18 
     19     void print() const;
     20 
     21     void SetPoint(int x, int y);
     22 
     23     int GetX() const;
     24 
     25     int GetY() const;
     26 
     27     /**
     28      *@author        qioawei
     29      *@date          2018-02-05
     30      *@version       1.0
     31      *@brief         = 赋值操作符
     32      *@called by
     33      *@param         rvalue 赋值变量
     34      *@return        赋值后
     35      **/
     36     Ch09_Point& operator = (const Ch09_Point& rvale);
     37 
     38     friend Ch09_Point operator + (const Ch09_Point& a, const Ch09_Point& b);
     39 
     40 private:
     41     int x_;
     42     int y_;
     43 };
     44 




    45 Ch09_Point.cpp: 46 47 #include "ch09_point.h" 48 49 Ch09_Point::Ch09_Point() : 50 x_(0), 51 y_(0) 52 { 53 54 } 55 56 Ch09_Point::Ch09_Point(int x, int y) : 57 x_(x), 58 y_(y) 59 { 60 61 } 62 63 Ch09_Point::Ch09_Point(const Ch09_Point &p) 64 { 65 x_ = p.x_; 66 y_ = p.y_; 67 } 68 69 void Ch09_Point::print() const 70 { 71 qDebug() << "x = " << x_ << ", y = " << y_ << endl; 72 } 73 74 void Ch09_Point::SetPoint(int x, int y) 75 { 76 x_ = x; 77 y_ = y; 78 } 79 80 int Ch09_Point::GetX() const 81 { 82 return x_; 83 } 84 85 int Ch09_Point::GetY() const 86 { 87 return y_; 88 } 89 90 Ch09_Point& Ch09_Point::operator = (const Ch09_Point &rvale) 91 { 92 if (this != &rvale) { 93 x_ = rvale.x_; 94 y_ = rvale.y_; 95 } 96 97 return *this; 98 } 99 100 Ch09_Point operator + (const Ch09_Point &a, const Ch09_Point &b) 101 { 102 return Ch09_Point(a.x_ + b.x_, a.y_ + b.y_); 103 }

    使用情况:

     1 Ch09_Point a1; //调用无参构造函数
     2 Ch09_Point a2(a1); //调用拷贝构造函数
     3 Ch09_Point a3 = a1; //调用拷贝构造函数
     4 Ch09_Point a4;
     5 a4 = a2 //赋值操作符
     6 
     7 //特殊情况
     8 Ch09_Point* a5(new A());
     9 Ch09_Point  a6(*a5) //调用拷贝构造函数
    10 Ch09_Point* p3 = new Ch09_Point(10, 20);   //构造函数
    11 a6 = *p3; //赋值操作符
    12 Ch09_Point p4(*p3);   //拷贝构造函数

    “=”在对象声明语句中表示初始化,调用拷贝构造函数;在非声明语句中表示赋值,调用赋值构造函数。

     Ch09_CopyConstructor类作为容器类,保存Ch09_Point类型指针,具体如下:

     1 ch09_copyconstructor.h
     2 
     3 class Ch09_Point;
     4 
     5 class Ch09_CopyConstructor
     6 {
     7 public:
     8     explicit Ch09_CopyConstructor();
     9     explicit Ch09_CopyConstructor(int x, int y);
    10 
    11     /**
    12      *@author        qioawei
    13      *@date          2018-02-05
    14      *@version       1.0
    15      *@brief         拷贝构造函数
    16      *@called by
    17      *@param         cc
    18      **/
    19     Ch09_CopyConstructor(const Ch09_CopyConstructor& cc);
    20 
    21     ~Ch09_CopyConstructor();
    22 
    23     Ch09_CopyConstructor& operator = (const Ch09_CopyConstructor& rvalue);
    24 
    25     void Print() const;
    26 
    27 private:
    28     Ch09_Point* p_;
    29 };
    30 
    31 ch09_copyconstructor.cpp
    32 
    33 #include "ch09_copyconstructor.h"
    34 
    35 #include "ch09_point.h"
    36 
    37 Ch09_CopyConstructor::Ch09_CopyConstructor() :
    38     p_(new Ch09_Point(0, 0))
    39 {
    40 
    41 }
    42 
    43 Ch09_CopyConstructor::Ch09_CopyConstructor(int x, int y) :
    44     p_(new Ch09_Point(x, y))
    45 {
    46 }
    47 
    48 Ch09_CopyConstructor::Ch09_CopyConstructor(const Ch09_CopyConstructor &cc)
    49 {
    50     if (this != &cc) {
    51         delete p_;
    52 
    53         //调用Ch09_Point的拷贝构造函数
    54         p_ = new Ch09_Point(*(cc.p_));
    55     }
    56 }
    57 
    58 Ch09_CopyConstructor::~Ch09_CopyConstructor()
    59 {
    60     delete p_;
    61 
    62     //qDebug() << "from base class" << endl;
    63 }
    64 
    65 Ch09_CopyConstructor& Ch09_CopyConstructor::operator =(const Ch09_CopyConstructor& rvalue)
    66 {
    67     if (this != &rvalue) {
    68         delete p_;
    69         //调用Ch09_Point拷贝构造函数?
    70         p_ = new Ch09_Point(*(rvalue.p_));
    71     }
    72 
    73     return *this;
    74 }
    75 
    76 void Ch09_CopyConstructor::Print() const
    77 {
    78     p_->print();
    79 }

    因为p_变量在构造函数中进行初始化,在进行拷贝构造或者赋值操作时需要先判断,如与所赋对象不一致,则需要先delete p_的实例,随后创建新实例保存所赋对象中数据。

    Ch09_DeprivedClass类作为Ch09_CopyConstructor的子类,同时在Ch09_DeprivedClass类中保存一个Ch09_Point类作为变量保存。

     1 Ch09_DeprivedClass.h
     2 
     3 class Ch09_Point;
     4 
     5 class Ch09_DeprivedClass : public Ch09_CopyConstructor
     6 {
     7 public:
     8     explicit Ch09_DeprivedClass();
     9     explicit Ch09_DeprivedClass(int x, int y);
    10 
    11     Ch09_DeprivedClass(const Ch09_DeprivedClass& dc);
    12 
    13     virtual ~Ch09_DeprivedClass();
    14 
    15     Ch09_DeprivedClass& operator =(const Ch09_DeprivedClass& dc);
    16 
    17     void PrintDeprivedClass();
    18 
    19 public:
    20     Ch09_Point* deprived_p_;
    21 };
    22 
    23 Ch09_DeprivedClass.cpp
    24 
    25 #include "ch09_deprivedclass.h"
    26 
    27 #include "ch09_point.h"
    28 
    29 Ch09_DeprivedClass::Ch09_DeprivedClass() :
    30     Ch09_CopyConstructor(),
    31     deprived_p_(new Ch09_Point(0, 0))
    32 {
    33     qDebug() << deprived_p_ << endl;
    34 }
    35 
    36 Ch09_DeprivedClass::Ch09_DeprivedClass(int x, int y) :
    37    Ch09_CopyConstructor(x, y),
    38    deprived_p_(new Ch09_Point(x + 11, y + 22))
    39 {
    40     qDebug() << deprived_p_ << endl;
    41 }
    42 
    43 Ch09_DeprivedClass::Ch09_DeprivedClass(const Ch09_DeprivedClass &dc) :
    44     Ch09_CopyConstructor(dc)        //调用基类拷贝构造函数
    45 {
    46     if (this != &dc) {
    47         delete deprived_p_;
    48 
    49         deprived_p_ = new Ch09_Point(*(dc.deprived_p_));
    50         //deprived_p_ = new Ch09_Point(dc.deprived_p_->GetX(), dc.deprived_p_->GetY());
    51     }
    52 }
    53 
    54 Ch09_DeprivedClass::~Ch09_DeprivedClass()
    55 {
    56     delete deprived_p_;
    57 
    58     //qDebug() << "from deprived class" << endl;
    59 }
    60 
    61 Ch09_DeprivedClass &Ch09_DeprivedClass::operator =(const Ch09_DeprivedClass &dc)
    62 {
    63     if (this != &dc) {
    64         delete this;
    65 
    66         //调用基类赋值操作符,完成基类private变量的赋值
    67         Ch09_CopyConstructor::operator =(dc);
    68         deprived_p_ = new Ch09_Point(*(dc.deprived_p_));
    69     }
    70 
    71     return *this;
    72 }
    73 
    74 void Ch09_DeprivedClass::PrintDeprivedClass()
    75 {
    76     Print();
    77 
    78     qDebug() << " deprived x = " << deprived_p_->GetX()
    79              << ", deprived y = " << deprived_p_->GetY() << endl;
    80 }

    在拷贝构造函数中需要调用基类的拷贝构造函数;在赋值操作符中调用基类赋值操作符,给基类中保存的private变量赋值。

  • 相关阅读:
    csp 初赛 (不懂的地方)
    4月11日晚科目一练习(95分)
    在博客园利用 MathJax 建支持 $\LaTeX$ 的博客
    4月9日科目一练习(88分)
    阿狸的故事
    4月10日晚科目一练习(95分)
    复变函数自身运动的三个节点
    4月11日科目一练习(97分)
    4月10日科目一练习(92分)
    极限题(4.5)
  • 原文地址:https://www.cnblogs.com/weiweiqiao99/p/14288884.html
Copyright © 2011-2022 走看看