• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
qwz185_十秒耿直拆包选手
博客园    首页    新随笔    联系   管理    订阅  订阅
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变量赋值。

posted on 2021-01-17 14:24  qz185_十秒拆包选手  阅读(183)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3