기호가 같은 연산자를 여러 가지 기능을 가질 수 있도록 정의할 수 있다. 이를 연산자 오버로딩
이라고 한다.
#include <iostream>
using namespace std;
class String
{
public:
String(char ch, int nSize);
~String();
void operator=(const String& s);
void SetData();
private:
int nLength;
char *pBuffer;
};
String::String(char ch, int nSize)
{
nLength = nSize;
pBuffer = new char[nLength + 1];
memset(pBuffer, ch, nLength);
pBuffer[nLength] = '\0';
cout << "pBuffer : " << pBuffer << endl;
cout << "nLength : " << nLength << endl;
}
String::~String()
{
delete[] pBuffer;
}
void String::operator=(const String& s) // & : CallbyReference하겠다!
{
delete pBuffer;
nLength = s.nLength;
pBuffer = new char[nLength + 1];
strcpy(pBuffer, s.pBuffer);
}
void String::SetData()
{
cout << "pBuffer : " << this->pBuffer << endl;
cout << "nLength : " << this->nLength << endl;
}
int main()
{
String str1('A', 5);
String str2('B', 5);
str1 = str2;
}
pBuffer : AAAAA
nLength : 5
pBuffer : BBBBB
nLength : 5
str1 = str2;
str2.operator=(str1);
두 문장 모두 같은 것이다. 위처럼 본다면 더 직관적으로 이해할 수 있다.
str1 = str1;
자기 자신을 대입시 먼저 str1
이 가르키는 메모리가 delete될것이고, 새로운 메모리 공간을 힙영역에 nLength
길이만큼 할당한다. 문제는 strcpy()
시에 s.pBuffer
값을 가지고 올 수 없으므로 결국 복사는 실패하게 된다.
void String::operator=(const String& s)
{
if(&s == this)
return;
delete pBuffer;
nLength = s.nLength;
pBuffer = new char[nLength + 1];
strcpy(pBuffer, s.pBuffer);
}
operator=()
멤버함수에서 전달인자로 넘겨받은 클래스 객체와 현재 멤버함수의 소속 클래스가 같은지 검사해서 코드는 실행되지 않도록 return
처리하면 문제를 해결할 수 있다.
String str1('A',3);
String str2 = str1; // 복사 생성자1
String str2(str1); // 복사 생성자2
객체 생성 시 초기화를 하되, 생성되는 객체를 다른 객체로 초기화 할 때 호출되는 생성자.
#include <iostream>
using namespace std;
class String
{
public:
String(char ch, int nSize);
~String();
String(const String& s);
void operator=(const String& s);
void SetData();
private:
int nLength;
char *pBuffer;
};
String::String(char ch, int nSize)
{
nLength = nSize;
pBuffer = new char[nLength + 1];
memset(pBuffer, ch, nLength);
pBuffer[nLength] = '\0';
// cout << "pBuffer : " << pBuffer << endl;
// cout << "nLength : " << nLength << endl;
}
String::~String()
{
delete[] pBuffer;
}
String::String(const String& s)
{
this->nLength = s.nLength;
this->pBuffer = new char[this->nLength + 1];
strcpy(this->pBuffer, s.pBuffer);
}
void String::operator=(const String& s)
{
if(&s == this)
return;
delete pBuffer;
this->nLength = s.nLength;
this->pBuffer = new char[this->nLength + 1];
strcpy(this->pBuffer, s.pBuffer);
}
void String::SetData()
{
cout << "pBuffer : " << this->pBuffer << endl;
cout << "nLength : " << this->nLength << endl;
}
int main()
{
String str1('A', 5);
String str2(str1);
// String str2 = str1; 윗문장과 같음
cout << "대입 후 str2" << endl;
str2.SetData();
}
대입 후 str2
pBuffer : AAAAA
nLength : 5
operator
에서는 pBuffer
를 delete
를 해주었지만, 복사생성자에서는 delete
를 하지 않는다. 그 이유는 operator
에서는 기존에 있던 데이터를 없애고 값을 받아야 했지만, 복사 생성자에서는 객체가 처음 생성되는 시점이기 때문에 delete
할 필요가 없기 때문이다.