728x90
황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!
https://search.shopping.naver.com/book/catalog/32436115747
단항 연산자
단항 연산자(unary operator)란 앞에서 본 이항 연산자와는 다르게 피연산자가 하나이다. 위치에 따라 전위 연산자(prefix operator)와 후위 연산자(postfix operator)로 나뉜다.
전위 연산자 : !op, ~op, ++op, --op ....
후위 연산자 : op++, op-- ....
전위 ++ 연산자 중복
#include <iostream>
using namespace std;
class Power {
int kick;
int punch;
public:
Power(int kick=0, int punch=0) {
this->kick = kick; this->punch = punch;
}
void show();
Power& operator++ (); // 전위 ++ 연산자 함수 선언
};
void Power::show() {
cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power& Power::operator++() {
kick++;
punch++;
return *this; // 변경된 객체 자신(객체 a)의 참조 리턴
}
int main() {
Power a(3,5), b;
a.show();
b.show();
b = ++a; // 전위 ++ 연산자 사용
a.show();
b.show();
}
! 연산자 작성
#include <iostream>
using namespace std;
class Power {
int kick;
int punch;
public:
Power(int kick=0, int punch=0) {
this->kick = kick; this->punch = punch;
}
void show();
bool operator! (); // ! 연산자 함수 선언
};
void Power::show() {
cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
bool Power::operator!() {
if(kick == 0 && punch == 0) return true;
else return false;
}
int main() {
Power a(0,0), b(5,5);
if(!a) cout << "a의 파워가 0이다." << endl; // ! 연산자 호출
else cout << "a의 파워가 0이 아니다." << endl;
if(!b) cout << "b의 파워가 0이다." << endl; // ! 연산자 호출
else cout << "b의 파워가 0이 아니다." << endl;
}
후위 ++ 연산자 중복
- 전위 연산자와 후위 연산자를 구분하기 위해 후위 연산자 함수는 매개 변수를 가지도록 선언한다.
Power operator++(); // 전위
Power operator++(int x); // 후위, 매개 변수 x에는 의미 없는 값이 전달되므로 무시해도 된다.
#include <iostream>
using namespace std;
class Power {
int kick;
int punch;
public:
Power(int kick=0, int punch=0) {
this->kick = kick; this->punch = punch;
}
void show();
Power operator++ (int x); // 후위 ++ 연산자 함수 선언
};
void Power::show() {
cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power Power::operator++(int x) {
Power tmp = *this; // 증가 이전 객체 상태를 저장
kick++;
punch++;
return tmp; // 증가 이전 객체 상태 리턴
}
int main() {
Power a(3,5), b;
a.show();
b.show();
b = a++; // 후위 ++ 연산자 사용
a.show(); // a의 파워는 1 증가됨
b.show(); // b는 a가 증가되기 이전 상태를 가짐
}
// 다양한 이항 연산자를 클래스의 연산자 멤버 함수로 선언한 예
Power operator + (Power op2) ==> Power operator + (Power& op2)
bool operator != (Power op2)
Power& operator += (Power op2)
Power operator + (int b)
bool operator > (int b)
Power& operator += (int b)
// 다양한 단항 연산자를 클래스의 연산자 멤버 함수로 선언한 예
bool operator ! ()
Power operator ~ ()
Power& operator ++ ()
Power operator ++ (int x)
Power& operator -- ()
Power operator -- (int x)
프렌드를 이용한 연산자 중복
- 지금까지는 클래스의 멤버 함수로 작성하였지만, 연산자 함수는 클래스 바깥의 외부 전역 함수로도 작성 가능
- 연산자 함수를 클래스에서 friend로 취하여 클래스 멤버를 자유롭게 접근할 수 있게 한다.
2+a를 위한 + 연산자 함수 작성
Power a(3, 4), b;
b = 2+a;
// 지금까지는 아래와 같이 변형한다.
2 . + (a)
- 그러나 2가 객체가 아니므로, 위의 변형식은 잘못된 문장이다.
- 즉, 첫 번째 피연산자가 객체가 아닌 경우 아래와 같이 변형한다.
+ (2, a)
- 이처럼 연산자 함수를 오직 외부 함수로만 작성해야 하는 경우가 있다.
외부 연산자 함수의 프렌드 선언
- operator+(int, Power) 연산자 함수에는 하나의 걱정이 있다.
- 함수 내에서 Power의 private 멤버인 kick과 punch를 자유롭게 접근하고 있기 때문이다.
- 이를 해결하기 위하여 kick과 punch를 public으로 선언하게 된다면 캡슐화 원칙을 무너뜨리는 꼴이다.
- 따라서, friend 함수를 사용하면 깔끔하게 해결된다.
#include <iostream>
using namespace std;
class Power {
int kick;
int punch;
public:
Power(int kick=0, int punch=0) {
this->kick = kick; this->punch = punch;
}
void show();
friend Power operator+(int op1, Power op2); // 프렌드 선언
};
void Power::show() {
cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power operator+(int op1, Power op2) {
Power tmp; // 임시 객체 생성
tmp.kick = op1 + op2.kick; // kick 더하기
tmp.punch = op1 + op2.punch; // punch 더하기
return tmp; // 임시 객체 리턴
}
int main() {
Power a(3,5), b;
a.show();
b.show();
b = 2 + a; // 파워 객체 더하기 연산
a.show();
b.show();
}
+ 연산자를 외부 프렌드 함수로 작성
#include <iostream>
using namespace std;
class Power {
int kick;
int punch;
public:
Power(int kick=0, int punch=0) {
this->kick = kick; this->punch = punch;
}
void show();
friend Power operator+(Power op1, Power op2); // 프렌드 선언
};
void Power::show() {
cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power operator+(Power op1, Power op2) {
Power tmp; // 임시 객체 생성
tmp.kick = op1.kick + op2.kick; // kick 더하기
tmp.punch = op1.punch + op2.punch; // punch 더하기
return tmp; // 임시 객체 리턴
}
int main() {
Power a(3,5), b(4,6), c;
c = a + b; // 파워 객체 더하기 연산
a.show();
b.show();
c.show();
}
잊지 말아야 될 것이 하나의 연산자 함수를 멤버 함수와 프렌드 함수로 동시에 구현할 수 없다!!
단항 연산자 ++를 프렌드로 작성하기
- 단항 연산자 ++를 변경할 때 매우 중요한 점이 있다.
- 두 연산자 모두 Power& op를 사용하며, 전위 연산자의 경우 참조를 리턴한다는 점이다..!
- Power& op의 참조 매개 변수를 사용함으로써 op는 객체 a를 참조하게 되어 op 객체를 변경하면 바로 객체 a가 변경된다.
#include <iostream>
using namespace std;
class Power {
int kick;
int punch;
public:
Power(int kick=0, int punch=0) { this->kick = kick; this->punch = punch; }
void show();
friend Power& operator++(Power& op); // 전위 ++ 연산자 함수 프렌드 선언
friend Power operator++(Power& op, int x); // 후위 ++ 연산자 함수 프렌드 선언
};
void Power::show() {
cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power& operator++(Power& op) { // 전위 ++ 연산자 함수 구현
op.kick++;
op.punch++;
return op; // 연산 결과 리턴
}
Power operator++(Power& op, int x) { // 후위 ++ 연산자 함수 구현
Power tmp = op; // 변경하기 전의 op 상태 저장
op.kick++;
op.punch++;
return tmp; // 변경이전의 op 리턴
}
int main() {
Power a(3,5), b;
b = ++a; // 전위 ++ 연산자
a.show(); b.show();
b = a++; // 후위 ++ 연산자
a.show(); b.show();
}
TIP!! 연산자 함수는 멤버 함수나 프렌드 함수 중 어떤 것이 바람직한가?
- 가능하면 클래스의 멤버 함수로 작성하기를 권한다.
- 새로운 연산자는 클래스와 연계하여 작동하기 때문에!
- 멤버로 선언하면 외부의 연산자 함수를 friend로 취할 필요도 없고 가독성도 높아지기 때문이다.
- 또한 연산자 함수는 디폴트 매개 변수를 가질 수 없다..!
실습 : 참조를 리턴하는 << 연산자 작성해보기
#include <iostream>
using namespace std;
class Power {
int kick;
int punch;
public:
Power(int kick = 0, int punch = 0) {
this->kick = kick; this->punch = punch;
}
void show();
Power& operator << (int n); // 연산 후 Power 객체의 참조 리턴
};
void Power::show() {
cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power& Power::operator <<(int n) {
kick += n;
punch += n;
return *this; // 이 객체의 참조 리턴
}
int main() {
Power a(1, 2);
a << 3 << 5 << 6; // 객체 a에 3,5,6이순서대로 더해진다.
a.show();
}
728x90
'Programming Language > C++' 카테고리의 다른 글
[C++] 상속과 객체 포인터 (0) | 2023.12.14 |
---|---|
[C++] 상속 (1) | 2023.12.06 |
[C++] 연산자 중복 (0) | 2023.12.06 |
[C++] 프렌드 (1) | 2023.12.05 |
[C++] static 멤버 (0) | 2023.12.05 |