피연산자의 자료형과 연산자
- 동일한 연산자라도 구체적인 처리 방법은 피연산자의 자료형에 따라 달라진다.
연산자 다중정의란?
- c++ 에 정의된 연산자를 사용자가 선언한 클래스의 객체에 대하여 사용 할 수 있도록 정의 하는 것
- 연산자의 의미를 임의로 바꾸지 않는다.
- 고유의 특성이 유지되도록 한다.
연산자의 다중정의 위치
- 클래스의 멤버로 정의하는 방법
- → 연산자의 구현 과정에서 객체의 멤버를 액세스 할 수 있음
- 클래스 외부에서 정의하는 방법
- → 클래스의 멤버가 아니므로, 객체의 private 멤버는 직접 사용 x
다중정의 형식
전위 표기법
ReturnClass ClassName::operator opSymbol()
{
······
}
opSymbol : ++ , — 등의 단항 연산자 기호
형식 매개변수 x
후위 표기법
ReturnClass ClassName::operator opSymbol(int)
{
······
}
형식 매개변수 표기는 인수 전달의 의미가 아닌 후위 표기법임을 나타냄
이항 연산자의 다중정의
ReturnClass ClassName::operator opSymbol(ArgClass arg)
{
······
}
opSymbol : +, -, *, /, &&, || 등의 이항 연산자 기호
객체 자신이 좌측 피연산자, arg가 우측 피연산자에 해당됨
복소수 객체와 복소수 객체의 덧셈 연산자
// 수식 : complex2Obj1 + complex2Obj2
Complex2 Complex2::operator + (const Complex2 &c) const
// complex2Obj1 = *this
// c = complex2Obj2
{
······
}
실수와 복소수의 객체의 덧셈 연산자
좌측 피연산자가 실수이므로 Complex2 클래스의 멤버로 연산자를 정의할 수 없음
// 수식 : 10.0 + complex2Obj
// error private 멤버 사용
Complex2 operator + (double r, const Complex2 &c)
{
return Complex2(r + c.rPart, c.iPart);
}
에러 해결 1
private 멤버를 엑세스 할 수 있는 멤버함수 정의
class Complex2 {
double rPart, iPart;
public:
······
double real() const { return rPart; } // 실수부의 값 반환
double imag() const { return iPart; } // 허수부의 값 반환
};
Complex2 operator + (double r, const Complex2 &c)
{
return Complex2(r + c.real(), c.imag());
}
에러 해결2
다중 정의 된 연산자를 friend 로 선언
class Complex2 {
double rPart, iPart;
public:
······
friend Complex2 operator + (double r, const Complex2& c);
};
Complex2 operator + (double r, const Complex2 &c)
{
return Complex2(r + c.rPart, c.iPart);
}
대입연산자 (=)
- 묵시적 대입 연산자 : 우측 피연산자 데이터 멤버를 좌측 피연산자에 그대로 복사함
- 객체에 동시 할당된 메모리를 가리키는 포인터가 포함되어 있을 경우 얕은 복사가 된다. (공유 상태 문제 발생)
→ 깊은 복사 필요
// VecF :: operator -> a = fv -> b / a = b
VecF& VecF :: operator = (const VecF& fv){
if (n != fv.n) { // 백터가 n이 아니라면
delete[] arr; // 기존 메모리 초기화
arr = new float[n = fv.n]; // 메모리 할당
}
memcpy(arr, fv.arr, sizeof(float)*n); // 데이터 복사
return *this;
}
이동대입연산자(=)
- 좌측 피연산자에 대입 할 우측 피연산자가 rvalue 일 때 사용 됨
- → 대입 후 우측 피연산자의 내용이 더이상 필요 없는 상황
VecF& VecF :: operator = (VecF&& fv){ // 우측피연산자는 값이 바뀔 수 있기에 const 안씀
delete[] arr; // 기존 메모리 초기화
n = fv.n; // 우측 피연산자의 내용을 이동
arr = fv.arr;
fv.arr = nullptr;
return *this;
}
두 VecF 객체를 교환하는 함수의 구현
std::move 함수 사용
- 인수로 전달되는 객체의 rvalue 참조를 반환
VecF tmp = std :: move(v1);
→ v1의 rvalue 참조를 구하여 tmp의 초기화에 사용
→ 이동 생성자를 이용하여 tmp 생성
v1 = std::move(v2);
→ v2 의 rvalue 참조를 구하여 v1에 대입
→ 이동 대입 연산자 실행
[ ] 연산자의 다중정의
[ ] 연산자
- 배열의 첨자를 지정하는 이항 연산자
- 피연산자 → 배열의 첨자
데이터를 저장하기 위해 사용할 [ ] 연산자
SafeIntArray a(10);
a[5] = 10;
int& SafeIntArray::operator[](int i){
// 좌측 피연산자 a = *this // 매개변수 i = [5]
......
}
const 객체를 위한 [ ] 연산자
- 데이터를 읽기만 할 수 있도록 [ ] 연산자를 정의함
- const 는 읽기 전용이기에, 그냥 첨자 연산자의 다중정의로는 error 가 나온다 const로 두번 지정해줘야함
void f(const SefeIntArray & x) {
for(int i = 0; i < x.size(); i++)
const << x[i] << endl;
}
int SafeIntArray::operator[](int i) const {
......
}
728x90
'KNOU > C++' 카테고리의 다른 글
[C++프로그래밍] 예외처리 (0) | 2022.12.01 |
---|---|
[C++ 프로그래밍]템플릿 (0) | 2022.12.01 |
[C++ 프로그래밍] 클래스와 객체 (0) | 2022.12.01 |
[C++ 프로그래밍] 함수 (1) | 2022.12.01 |
댓글