■ C++ 연산자 오버로딩 2(대입, 배열의 인덱스, new/delete 연산자)
ㆍ 대입 연산자 오버로딩
- 디폴트 복사 생성자와 마찬가지로 기본적으로 "디폴트 대입 연산자"가 있다.
=> 디폴트 대입 생성자는 멤버 대 멤버의 복사(얕은 복사)를 하기 때문에, 동적 할당 시 에러가 발생한다. 이를 해결하기 위해 깊은 복사를 하는 대입 연산자를 정의해야 한다.
- person1 = person2
=> person1.operator=(person2)
ex>
class Person
{
private:
char* name;
int age;
public:
Person(char* myname, int myage) : age(myage)
{
name = new char[strlen(myname)+1];
strcpy(name, myname);
}
Person& operator=(const Person& ref)
{
delete []name;
name = new char[strlen(ref.name)+1];
strcpy(name, ref.name);
age=ref.age;
return *this;
}
}
* 상속 관계의 경우, 하위 클래스의 대입 연산자의 정의에서 명시적으로 상위 클래스의 대입 연산자 호출 문을 삽입해야 한다.
=> Person::operator=(ref);
ㆍ 배열의 인덱스 연산자 오버로딩
- 인덱스 연산자 오버로딩은 다음과 같이 해석된다.
=> arr[3] == arr.operator[](2);
ex>
typedef Person* PERSON_PTR;
class SimpleArray
{
private:
PERSON_PTR *arr;
int arrlen;
SimpleArray(const SimpleArray& arr){} // private로 선언함으로써,
SimpleArray& operator=(const SimpleArray& arr){} // 복사가 되지 않도록 함
public:
SimpleArray(const int& len) : arrlen(len)
{
arr=new PERSON_PTR[len];
}
PERSON_PTR& operator[](const int& idx) // 객체 참조 값 반환(l-value)
{
if(idx>=arrlen || idx<0)
{
exit(1);
}
return arr[idx];
}
PERSON_PTR operator[](const int& idx) // 객체 값 반환(r-value)
{
if(idx>=arrlen || idx<0)
{
exit(1);
}
return arr[idx];
}
...
};
ㆍ new/delete 연산자 오버로딩
1. new 연산자 오버로딩
- 먼저 new 연산자가 하는 일은 다음과 같다.
① 메모리 공간 할당
② 생성자의 호출
③ 할당하고자 하는 자료형에 맞게 반환된 주소 값의 형 변환
- 여기서 ②, ③은 C++ 컴파일러가 처리하기로 약속했기 때문에, new 연산자 오버로딩을 통해서 ①에 해당하는 메모리 공간 할당만 오버로딩할 수 있다.
- new 연산자 오버로딩 함수는 static 함수로 간주된다.
- void* operator new (size_t size) { ... }
- void* operator new[] (size_t size) { ... }
=> 위와 같이 return 형: void* / 매개변수형: size_t 로 약속되어 있다(typedef unsigned int size_t)
ex>
void* operator new(size_t size)
{
void* adr= new char[size];
return adr
}
* 필요한 메모리 공간의 크기가 바이트 단위로 계산되어서 인자로 전달되기 때문에, char 단위로 메모리 공간을 할당해서 반환
2. delete 연산자 오버로딩
- 먼저 delete 연산자 실행 시 진행되는 일은 다음과 같다( ex> delete ptr; )
① ptr이 가리키는 객체의 소멸자를 호출
② delete 연산자 오버로딩 함수에 ptr 주소 값 전달 및 실행
- 소멸자는 오버로딩 된 함수가 호출되기 전에 호출이 되니 오버로딩 된 함수에서 메모리 공간의 소멸을 해야 한다
- delete 연산자 오버로딩 함수는 static 함수로 간주된다.
- void* operator delete (void* adr) { ... }
- void* operator delete[] (void* adr) { ... }
=> 위와 같이 return 형: void* / 매개변수형: size_t로 약속되어 있다(typedef unsigned int size_t)
ex>
void* operator delete(void* adr)
{
delete []adr; // delete []((char*)adr), 컴파일러에서 void* 형에 대상의 delete 연산을 허용 안 할 시
}
'Coding > C & C++' 카테고리의 다른 글
C++ 템플릿 (0) | 2020.03.03 |
---|---|
C++ 연산자 오버로딩 3(포인터 , (), 형 변환 연산자) (0) | 2020.03.01 |
C++ 연산자 오버로딩 1(기본 연산자, 단항 연산자, << 연산자) (0) | 2020.02.26 |
C++ 가상 함수 (0) | 2020.02.25 |
C++ 상속 정리 (0) | 2020.02.24 |