프랜드란? 클래스 외부 함수(다른 클래스, 전역함수 등)임에도, private나, protect를 접근해야하는 특별한 경우에 이를 프랜드함수로 지정해 이를 접근할 수 있다.
include <iostream>
using namespace std;
class Rect; // 후방참조를 막기 위한 Rect클래스 선언
bool equals(Rect r, Rect s); //전역 함수를 선언
class Rect{
int width, height;
public:
Rect(int width, int height){
this->width = width;
this->height = height;
}
friend bool equals(Rect r, Rect s);
};
bool equals(Rect r, Rect s){
if(r.width == s.width && r.height == s.height) return true; //외부함수인 equals가,
//width와, height를 접근가능
else return false;
}
int main (){
Rect a(3,4), b(4,5);
if(equals(a,b)) cout << "equal" << endl;
else cout << "not equal" << endl;
}
참고로 전방참조, 후방참조는 자기위치 기준 앞의 코드를 읽는가, 뒤의 코드를 읽는가로 구분되며, 후방참조는 불가능하기에, 에러를 방지하기 위해 위와 같은 Rect클래스를 선언한것이다.
include <iostream>
using namespace std;
class Rect; // 후방참조를 막기 위한 Rect클래스 선언
class RectManager{
public:
bool equals(Rect r, Rect s);
};
class Rect{
int width, height;
public:
Rect(int width, int height){
this->width = width;
this->height = height;
}
friend bool RectManager::equals(Rect r, Rect s); //Rectmanager의 equals맴버함수를 프랜드 선언
//만약 RectManager전체를 friend하고 싶으면 함수없이
//friend RectManager 하면됨.
};
bool equals(Rect r, Rect s){
if(r.width == s.width && r.height == s.height) return true; //프랜드인 width과 height를 접근가능
else return false;
}
int main (){
Rect a(3,4), b(4,5);
RectManager man;
if(man.equals(a,b)) cout << "equal" << endl;
else cout << "not equal" << endl;
}
연산자 중복이란? +, - , *, / >>, <<, 와 같이, 본래있던 계산 기능에 추가기능을 넣을 수 있는 기능이다. 보통 객체간의 연산을 지원하기 위해 사용한다.
Color operator + (Color op1, Color op2)
class Color P
friend Color operator + (Color op1, Color op2);
Color operator + (Color op1)
class Color{
Color operator + (Color op1);
지금부터는 구체적 사용예를 살펴보겠다.
class Power{
int kick;
int punch;
public:
Power(int Kick=0, int punch=0){
this-> kick = kick;
this->punch = punch;
}
};
위와 같은 코드에서 아래와 같이 3개의 객체를 생성하고 a와 b를 더했다.
Power a(3,5), b(4,6), c;
c = a+b;
그러면 a와 b를 덧샘할 수 없음을 깨닫고, 아래와 같이 식을 변환한다.
c = a.+(b);// a의 맴버함수 operatror+()를 호출하여, b를 매개 변수로 넘겨주는 함수의 호출이다.
그후 새로운 power type의 객체 c를 출력한다.
class Power{
int kick;
int punch;
Public:
Power operator+ (Power op1); // operator+(.+), op1(b)
};
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); //+ 중복연산자 함수를 선언
bool operator==(Power op2); //== 중복연산자 함수를 선언
Power& operator+=(Power op2); //+= 중복연산자 함수를 선언
// 이때 a에는 복사값이 아닌 실제값을 가져오기위해 참조에 의한 복사 연산을 사용한다.
};
void Power::show(){
cout << "kick=" << kick << "punch=" << punch << endl;
};
Power Power::operator+(Power op2){ // +중복연산자 함수 구현
Power tmp;
tmp.kick = this->kick + op2.kick; //this->kick은 a의 kick이다.
tmp.punch = this->punch + op2.punch;
return tmp;
};
Power Power::operator==(Power op2){ // ==중복연산자 함수 구현
if(kick==op2.kick && punch==op2.punch) return true;
else return false;
};
Power &Power::operator+=(Power op2){ // +=중복연산자 함수 구현 + 참조에 의한 복사
kick = kick + op2.kick;
punch = punch + op2.punch;
return *this; //return *this란?
};
int main(){
Power a(3,5), b(4,6), c;
c = a+b; // c객체 생성후 더하기
a.show();
b.show();
c.show();
if(a == b) cout << "두 데미자가 같다." << endl;
else cout << "두 데미지가 같지 않다. << endl;
c= a+= b;
a.show();
b.show();
};
단항연산자란? 피연산자가 1개인 것으로 연산자의 위치에 따라 전위와 후위로 나뉜다.
전위: !op, ~op, ++op, --op
후위: op++, op--
전위와 후위에 따라, 구현부가 달라짐으로, 구현에 주의해야한다.
class Power{
int kick;
int punch;
public:
Power(int Kick=0, int punch=0){
this-> kick = kick;
this->punch = punch;
}
void show();
Power &operator++(); //++ 전위중복연산자 함수를 선언 + 실제값 변경 &사용
bool operator!();
};
void Power::show(){
cout << "kick=" << kick << "punch=" << punch << endl;
};
Power &Power::operator++(){ // ++전위 중복연산자 함수 구현
kick++;
punch++;
return *this; //실제값 변경위해, &사용 + this 반환
};
bool Power::operator!(){
if(kick ==0 && pusch ==0) return true;
else return false
int main(){
Power a(3,5), b;
b = ++a;
a.show();
b.show();
if(!a) cout << a의 데미지가 0이다. << endl;
else cout << a의 데미지가 0이 아니다. << endl;
if(!b) cout << b의 파워가 0이다 << endl;
else cout << a의 데미지가 0이 아니다. << endl;
}
후위연산자는 전위와 다르게 의미없는 매개변수 1개가 필요하다.
또한, 계산후에 값을 바꾸기 때문에 직접 주소를 받을 필요가 없다.
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++(intx){ // ++후위 중복연산자 함수 구현
Power tmp = *this; // 증가이전 값을 tmp에저장
punch++;
return *this;
return tmp; // tmp를 리턴한다.
};
외부함수로 중복연산자를 구현하려면 프랜드로 지정해야한다.
그냥 public선언하면 안되나 싶지만, 이는 캡슐화와 맞지 않는 코드 작성법이다.
또한 클래스 내부에서 구현과 다르게, 모든 객체를 매개변수로 받아와야 한다.
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 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();
참조리턴이란? 자기자신의 주소를 리턴하는 것을 의미한다.
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);
};
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; //3과 5와 6을 순서대로 중복연산자로 자기자신을 리턴하여 더한다.
a.show()