在 C++ 中實現賦值運算子過載

Jinku Hu 2023年10月12日
在 C++ 中實現賦值運算子過載

本文將介紹幾種如何在 C++ 中實現賦值運算子過載的方法。

使用複製賦值運算子在 C++ 中實現過載的賦值運算子

C++ 提供了過載運算子的功能,這是在特定類上呼叫內建運算子時呼叫自定義函式的一種常用方法。這些功能應有一個特殊的名稱,以 operator 開頭,後跟特定的操作符符號本身。例如,可以使用名為 operator= 的函式來實現自定義賦值運算子。賦值運算子通常應返回對其左側運算元的引用。請注意,如果使用者未明確定義副本賦值運算子,則編譯器會自動生成一個。當該類不包含在堆記憶體上手動賦值的任何資料成員時,生成的版本將具有足夠的功能。它甚至可以通過將每個元素賦值給相應的物件成員來處理陣列成員。但是,在處理動態記憶體資料成員時,它有缺點,如下面的示例程式碼所示。

#include <iostream>
#include <string>
#include <utility>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

class Person {
 public:
  Person() {
    name = new string;
    surname = new string;
  };
  Person(string n, string s) {
    name = new string(std::move(n));
    surname = new string(std::move(s));
  }
  Person(Person &p) {
    name = new string(*p.name);
    surname = new string(*p.surname);
  }

  ~Person() {
    delete name;
    delete surname;
  }

  void renamePerson(const string &n, const string &s) {
    name->assign(n);
    surname->assign(s);
  };

  void printPerson() { cout << *name << " " << *surname; }

 private:
  string *name;
  string *surname;
};

int main() {
  Person P1("Buddy", "Rich");
  Person P2 = P1;

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  P1.renamePerson("Jay", "Roach");

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  Person P3;
  P3 = P1;
  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  P1.renamePerson("Liam", "White");

  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  exit(EXIT_SUCCESS);
}

輸出:

Buddy Rich
Buddy Rich
Jay Roach
Buddy Rich
Jay Roach
Jay Roach
Liam White
Liam White

上面的程式碼僅明確定義了複製構造器,當將 P1 物件的內容賦值給 P3 物件時,會導致不正確的行為。請注意,第二次呼叫 P1.renamePerson 函式的第二次呼叫不應該修改 P3 物件的資料成員,但它修改了。解決方案是定義一個過載的賦值運算子,即複製賦值運算子。下一個程式碼片段實現了 Person 類的版本,該版本可以正確地複製賦值同一類的兩個物件。但是請注意,複製賦值功能中的 if 語句可確保即使將物件賦值給自身,操作符也可以正常工作。

#include <iostream>
#include <string>
#include <utility>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

class Person {
 public:
  Person() {
    name = new string;
    surname = new string;
  };
  Person(string n, string s) {
    name = new string(std::move(n));
    surname = new string(std::move(s));
  }
  Person(Person &p) {
    name = new string(*p.name);
    surname = new string(*p.surname);
  }

  ~Person() {
    delete name;
    delete surname;
  }

  Person &operator=(const Person &p) {
    if (this != &p) {
      *name = *(p.name);
      *surname = *(p.surname);
    }
    return *this;
  }

  void renamePerson(const string &n, const string &s) {
    name->assign(n);
    surname->assign(s);
  };

  void printPerson() { cout << *name << " " << *surname; }

 private:
  string *name;
  string *surname;
};

int main() {
  Person P1("Buddy", "Rich");
  Person P2 = P1;

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  P1.renamePerson("Jay", "Roach");

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  Person P3;
  P3 = P1;
  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  P1.renamePerson("Liam", "White");

  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  exit(EXIT_SUCCESS);
}

輸出:

Buddy Rich
Buddy Rich
Jay Roach
Buddy Rich
Jay Roach
Jay Roach
Liam White
Jay Roach
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 創辦人。Jinku 在機器人和汽車行業工作了8多年。他在自動測試、遠端測試及從耐久性測試中創建報告時磨練了自己的程式設計技能。他擁有電氣/ 電子工程背景,但他也擴展了自己的興趣到嵌入式電子、嵌入式程式設計以及前端和後端程式設計。

LinkedIn Facebook

相關文章 - C++ Class