7장. 프렌드와 연산자 중복
C++ 프렌드
프렌드 함수
•
클래스의 멤버 함수가 아닌 외부 함수
◦
전역 함수
◦
다른 클래스의 멤버 함수
•
friend 키워드로 클래스 내에 선언된 함수
◦
클래스의 모든 멤버를 접근할 수 있는 권한 부여
◦
프렌드 함수
•
프렌드 선언의 필요성
◦
클래스의 멤버로 선언하기에는 무리가 있고, 클래스의 모든 멤버를 자유롭게 접근할 수 있는 일부 외부 함수 작성 시
프렌드로 초대하는 3가지 유형
•
전역 함수 : 클래스 외부에 선언된 전역 함수
•
다른 클래스의 멤버 함수 : 다른 클래스의 특정 멤버 함수
•
다른 클래스 전체 : 다른 클래스의 모든 멤버 함수
프렌트 선언 3 종류
1.
외부 함수 equals() 를 Rect 클래스에 프렌드로 선언
class Rect {
...
friend bool equals(Rect r, Rect s);
};
C++
복사
2.
RectManager 클래스의 equals() 멤버 함수를 Rect 클래스에 프렌드로 선언
class Rect {
...
frined bool RectManager::equals(Rect r, Rect s);
};
C++
복사
3.
RectManager 클래스의 모든 멤버 함수를 Rect 클래스에 프렌드로 선언
class Rect {
...
frined RectManager;
};
C++
복사
예제) 프렌드 함수 만들기
#include <iostream>
using namespace std;
class Rect; // Rect 클래스가 선언되기 전에 먼저 참조되는 컴파일 오류(forward reference)
// 를 막기위한 선언문 (forward declaration)
bool equals(Rect r, Rect s); // equals() 함수 선언
class Rect {
int width, height;
public:
Rect(int width, int height) { this->width = width; this->height = height; }
friend bool equals(Rect r, Rect s); //equals() 함수를 프렌드로 선언
};
bool equals(Rect r, Rect s) {
if (r.width == s.width && r.height == s.height) return true;
else return false;
}
// equals() 함수는 private 속성을 가진 width, height 에 접근할 수 있다
int main() {
Rect a(3, 4), b(4, 5);
if (equals(a, b)) cout << "equals" << endl;
else cout << "not equal" << endl;
}
C++
복사
예제2) 다른 클래스의 멤버 함수를 프렌드로 선언
예제3) 다른 클래스 전체를 프렌드로 선언
연산자 중복
중복의 사례) + 연산자
연산자 중복의 특징
•
C++ 에 본래 있는 연산자만 중복 가능
•
피 연산자 타입이 다른 새로운 연산 정의
•
연산자는 함수 형태로 구현 - 연산자 함수(operator function)
•
반드시 클래스와 관계를 가진다
•
피연산자의 개수를 바꿀 수 없다
•
연산의 우선순위 변경이 안된다
•
모든 연산자가 중복 가능하진 않다
중복 불가능한 연산자 :
- .
- .*
- :: (범위지정 연산자)
- ? : (3항 연산자)
연산자 함수
•
연산자 함수 구현 방법 2가지
◦
클래스의 멤버 함수로 구현
◦
외부 함수로 구현하고 클래스에 프렌드 함수로 선언
•
연산자 함수 형식
◦
리턴타입 operator연산자 (매개변수리스트);
•
+ 와 == 연산자의 작성 사례
멤버 함수와 이항 연산자 구현
이항 연산자 중복 : + 연산자
예제) 두 개의 Power 객체를 더하는 + 연산자 작성
#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+ (Power op2); // + 연산자 함수 선언
};
void Power::show() {
cout << "kick = " << kick << ", " << "punch = " << punch << endl;
}
Power Power::operator+(Power op2) { // + 연산자 멤버 함수 구현
Power tmp; // 임식 객체 생성
tmp.kick = this->kick + op2.kick; // kick 더하기
tmp.punch = this->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();
}
C++
복사
== 연산자 중복
예제) 두 개의 Power 객체를 비교하는 == 연산자 작성
#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 == (Power op2); // == 연산자 함수 선언
};
void Power::show() {
cout << "kick = " << kick << ", " << "punch = " << punch << endl;
}
bool Power::operator==(Power op2) {
if (kick == op2.kick && punch == op2.punch) return true;
else return false;
}
//bool Power::operator==(const Power& op2) {
// if (kick == op2.kick && punch ==op2.punch)
// return true;
// else return false;
}
int main() {
Power a(3, 5), b(4, 6); // 2개의 동일한 파워 객체 생성
a.show();
b.show();
if (a == b) cout << "두 파워가 같다." << endl;
else cout << "두 파워가 다르다." << endl;
}
C++
복사
+= 연산자 중복
예제) 두 Power 객체를 더하는 += 연산자 작성
#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+= (Power op2); // == 연산자 함수 선언
};
void Power::show() {
cout << "kick = " << kick << ", " << "punch = " << punch << endl;
}
Power& Power::operator+=(Power op2) {
kick = kick + op2.kick; // kick 더하기
punch = punch + op2.punch;
return *this; // 합한 결과 리턴
}
int main() {
Power a(3, 5), b(4, 6), c; // 2개의 동일한 파워 객체 생성
a.show();
b.show();
c = a += b;
a.show();
c.show();
}
C++
복사
예제) + 연산자 작성(실습) : b = a + 2;
#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 op2); // + 연산자 함수 선언
};
void Power::show() {
cout << "kick = " << kick << ", " << "punch = " << punch << endl;
}
Power Power::operator+(int op2) {
Power tmp; // 임식 객체 생성
tmp.kick = kick + op2; // kick에 op2 더하기
tmp.punch = punch + op2;
return tmp; // 임시 객체 리턴
}
int main() {
Power a(3, 5), b;
a.show();
b.show();
b = a + 2; // 파워 객체와 정수 더하기
a.show();
b.show();
}
C++
복사
멤버 함수로 단항 연산자 구현
단항 연산자 중복
•
단항 연산자
◦
피연산자가 하나 뿐인 연산자
▪
연산자 중복 방식은 이항 연산자의 경우와 거의 유사
◦
단항 연산자 종류
▪
전위 연산자 (prefix operator)
•
!op, ~op, ++op, —op
▪
후위 연산자 (postfix operator)
•
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();
}
C++
복사
예제) Power 클래스에 ! 연산자 작성
#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;
}
C++
복사
후위 연산자 중복, ++ 연산자
•
매개변수가 하나 있는 임의의 정수를 써준다
◦
후위 연산과 전위 연산을 구분해주기 위해서
예제) 후위 ++ 연산자 작성
#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가 증가되기 이전 상태를 가짐
}
C++
복사
2 + a 덧셈을 위한 + 연산자 함수 작성
예제) 2+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+ (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;
tmp.punch = op1 + op2.punch;
// private 속성인 kick, punch 를 접근하도록 하기 위해, 연산자 함수를 friend로 선언해야함
return tmp; // 임식 객체 리턴
}
int main() {
Power a(3, 5), b;
a.show();
b.show();
b = 2 + a;
a.show();
b.show();
}
C++
복사
+ 연산자를 외부 프렌드 함수로 구현
예제) a + b 를 위한 연산자 함수를 프렌드로 작성
#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;
tmp.punch = op1.punch + op2.punch;
return tmp; // 임식 객체 리턴
}
int main() {
Power a(3, 5), b(4, 6), c;
c = a + b;
a.show();
b.show();
c.show();
}
C++
복사
단항 연산자 ++ 를 프렌드로 작성하기
예제) ++ 연산자를 프렌드로 작성한 예
#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();
}
C++
복사
예제) 참조를 리턴하는 << 연산자 작성
#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.show();
}
C++
복사
ㅇ