> For the complete documentation index, see [llms.txt](https://ezcode.gitbook.io/bnb-cpp/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ezcode.gitbook.io/bnb-cpp/operator-overloading/assignment.md).

# 대입연산자 오버로딩

## 기본 대입연산자 <a href="#ea-b8-b0-eb-b3-b8-eb-8c-80-ec-9e-85-ec-97-b0-ec-82-b0-ec-9e-90" id="ea-b8-b0-eb-b3-b8-eb-8c-80-ec-9e-85-ec-97-b0-ec-82-b0-ec-9e-90"></a>

잠시 복사생성자에 대해 복습합니다.\
복사생성자는 다음과 같은 특성이 있다.

* 정의하지 않으면 기본 복사 생성자가 삽입된다.
* 기본 복사생성자는 얕은복사를 진행한다.
* 동적할당을 하는 멤버가 있을 경우 깊은복사를 하기위해 직접 정의해야 한다.

대입연산자도 다음과 같은 특성이 있다.

* 정의하지 않으면 **기본 대입연산자** 가 삽입된다.
* 기본 대입연산자는 얕은복사를 진행한다.
* 동적할당을 하는 멤버가 있을 경우 깊은복사를 하기위해 직접 정의해야 한다.

앞서 복사생성자와 같은 문제가 발생하므로 객체 맴버중에 동적할당을 하여 깊은 복사가 필요한 경우에 대입연산자를 다중정의 해야 한다.

### 기본 대입연산자의 문제점 <a href="#ea-b8-b0-eb-b3-b8-eb-8c-80-ec-9e-85-ec-97-b0-ec-82-b0-ec-9e-90-ec-9d-98-eb-ac-b8-ec-a0-9c-ec-a0-90" id="ea-b8-b0-eb-b3-b8-eb-8c-80-ec-9e-85-ec-97-b0-ec-82-b0-ec-9e-90-ec-9d-98-eb-ac-b8-ec-a0-9c-ec-a0-90"></a>

```cpp
#include <iostream>
#include <cstring>
using namespace std;

class Person {
  char *name;
  int age;
public :
  Person() : age(0){
    name = NULL; // 빈객체가 소멸될때 에러가 delete연산을 막음
  }
  Person(const char* name, int age)
    : age(age)
  {
    this->name = new char[strlen(name) + 1];
    strcpy(this->name, name);
  }

  ~Person() {
    cout << name << " ~Person() 호출" << endl;
    delete[] name;
  }

  void showInfo() {
    cout << "이름 : " << name << endl;
    cout << "나이 : " << age << endl;
  }
};

int main() {
  Person man1("남기용", 43);
  Person man2;

  man2 = man1;
  man1.showInfo();
  man2.showInfo();
  return 0;
}
```

기본 대입연산자는 앝은복사를 진행하기 때문에 멤버변수 `name`이 동적할당되어 소멸자에 의해서 두번 삭제가 되기 때문에 오류가 발생된다.

### 대입연산자 오버로딩 <a href="#eb-8c-80-ec-9e-85-ec-97-b0-ec-82-b0-ec-9e-90-ec-98-a4-eb-b2-84-eb-a1-9c-eb-94-a9" id="eb-8c-80-ec-9e-85-ec-97-b0-ec-82-b0-ec-9e-90-ec-98-a4-eb-b2-84-eb-a1-9c-eb-94-a9"></a>

다음과 같이 Person 객체에 대입연산자 오버로딩을 하여 문제를 해결할 수 있다.

```cpp
Person& operator=(const Person& ref) {
  age = ref.age; // 정적멤버는 일반 대입한다.

  delete[] name; // 메모리 누수를 막기위한 메모리 해제
  name = new char[strlen(ref.name) + 1]; // 새로 할당받는다
  strcpy(name, ref.name);
  return *this;
}
```

## 상속구조에서 대입연산자 호출 <a href="#ec-83-81-ec-86-8d-ea-b5-ac-ec-a1-b0-ec-97-90-ec-84-9c-eb-8c-80-ec-9e-85-ec-97-b0-ec-82-b0-ec-9e-90-e" id="ec-83-81-ec-86-8d-ea-b5-ac-ec-a1-b0-ec-97-90-ec-84-9c-eb-8c-80-ec-9e-85-ec-97-b0-ec-82-b0-ec-9e-90-e"></a>

파생 클래스의 대입연산자에서 명시하지 않으면 기초클래스의 대입연산자는 호출되지 않는다.

```cpp
#include <iostream>
#include <cstring>
using namespace std;

class Person {
  char *name;
  int age;
public :
  Person() : age(0){
    name = NULL; 
  }
  Person(const char* name, int age)
    : age(age)
  {
    this->name = new char[strlen(name) + 1];
    strcpy(this->name, name);
  }

  virtual ~Person() {
    delete[] name;
  }

  virtual void showInfo() {
    cout << "이름 : " << name << endl;
    cout << "나이 : " << age << endl;
  }

  Person& operator=(const Person& ref) {
    age = ref.age;

    delete[] name;
    name = new char[strlen(ref.name) + 1];
    strcpy(name, ref.name);
    return *this;
  }
};

class Student : public Person {
  char * school;
public :
  Student() {
    school = NULL;
  }

  Student(const char* name, int age, const char* school) 
    : Person(name, age)
  {
    this->school = new char[strlen(school) + 1];
    strcpy(this->school, school);
  }

  ~Student() {
    delete[] school;
  }

  virtual void showInfo() {
    Person::showInfo();
    cout << "학교 : " << school << endl;
  }

  Student& operator=(Student& ref) {
    delete[] school;
    school = new char[strlen(ref.school) + 1];
    strcpy(school, ref.school);
    return *this;
  }
};

int main() {
  Student man1("남기용", 43, "방송통신대학교");
  Student man2;

  man2 = man1;
  man1.showInfo();
  man2.showInfo();
  return 0;
}
```

Student 클래스의 `operator=`함수에서 Person 클래스의 대입이 이루어 지지 않기 때문에 `man2.name`은 NULL 값을 가지게 될 것이다.\
이러한경우 명시적으로 Person객체의 대입연산자를 호출하여야 한다.

Studend 클래스의 대입연산자를 다음과 같이 변경하자.

```cpp
Student& operator=(Student& ref) {
  Person::operator=(ref); // 기초 클래스의 대입연산자 호출

  delete[] school;
  school = new char[strlen(ref.school) + 1];
  strcpy(school, ref.school);
  return *this;
}
```
