앞서 복사생성자와 같은 문제가 발생하므로 객체 맴버중에 동적할당을 하여 깊은 복사가 필요한 경우에 대입연산자를 다중정의 해야 한다.
기본 대입연산자의 문제점
#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이 동적할당되어 소멸자에 의해서 두번 삭제가 되기 때문에 오류가 발생된다.
대입연산자 오버로딩
다음과 같이 Person 객체에 대입연산자 오버로딩을 하여 문제를 해결할 수 있다.
Person& operator=(const Person& ref) {
age = ref.age; // 정적멤버는 일반 대입한다.
delete[] name; // 메모리 누수를 막기위한 메모리 해제
name = new char[strlen(ref.name) + 1]; // 새로 할당받는다
strcpy(name, ref.name);
return *this;
}
상속구조에서 대입연산자 호출
파생 클래스의 대입연산자에서 명시하지 않으면 기초클래스의 대입연산자는 호출되지 않는다.
#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 클래스의 대입연산자를 다음과 같이 변경하자.
Student& operator=(Student& ref) {
Person::operator=(ref); // 기초 클래스의 대입연산자 호출
delete[] school;
school = new char[strlen(ref.school) + 1];
strcpy(school, ref.school);
return *this;
}