• 프로그래머는 대부분의 빌트인 연산자를 재정의하거나 오버로드할 수 있습니다.
• 프로그래머는 사용자 정의 유형을 가진 연산자를 사용할 수도 있습니다.
• 오버로드된 연산자는 키워드인 operator 뒤에 정의되는 연산자의 기호가 이어지는 특별한 이름을 가진 함수입니다.
• 다른 함수와 마찬가지로 오버로드된 연산자에는 반환 유형과 파라미터 목록이 있습니다.
ex> Plus Operator
Unit Unit::Operator+(Unit right){}
• 연산자의 우선순위는 오버로드의 영향을 받지 않습니다.
• 오버로드된 연산자는 기본값 매개변수를 사용할 수 없습니다.
• 연산자 ::(범위 확인), . (멤버 액세스), .*(멤버 포인터를 통한 멤버 액세스) 및 ?:(기본 조건)은 오버로드할 수 없습니다.
• **, <>, 또는 &| 등의 새 연산자를 생성할 수 없습니다.
• 연산자 =, [], () 및 ->는 멤버 함수로만 정의할 수 있습니다.
이항 연산자(+,-, 등등)
• 첫 번째(왼쪽) 개체는 연산자 오버로드 함수 발신자이고 두 번째(오른쪽) 개체는 전달된 인수입니다.
• 왼쪽 개체(함수 호출자)는 this 포인터를 사용하여 액세스할 수 있습니다.
ex1) - 연산자 오버로딩
#include <iostream>
using namespace std;
class Unit {
private:
int hp;
public:
Unit() { hp = 0; }
Unit(int i) { hp = i; }
int GetHP() { return hp; }
Unit operator-(Unit right);
};
Unit Unit::operator-(Unit right) {
Unit temp;
temp.hp = hp - right.hp;
return temp;
}
int main() {
Unit Unit1(10), Unit2(5), Unit3;
Unit3 = Unit1 - Unit2;
cout << "Unit1 hp : " << Unit1.GetHP() << endl;
cout << "Unit2 hp : " << Unit2.GetHP() << endl;
cout << "Unit3 hp : " << Unit3.GetHP() << endl;
}
연산자 오버로딩 함수에서 hp는 이항연산자의 좌측에 해당하는 unit의 hp, 이고 right.hp가 연산자의 우측에 있는 unit으로 매개변수로 쓰이는 것과 같이 실행된다.
ex2) 연산자 오버로딩 및 상속
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
class Unit {
private:
int hp;
int mp;
int unitSize;
char* name;
public:
Unit() {
hp = 0;
mp = 0;
unitSize = 0;
name = NULL;
}
Unit(int hp, int mp, int unitSize, const char* argName) : hp(hp), mp(mp), unitSize(unitSize) {
name = new char[strlen(argName) + 1];
strcpy(name, argName);
}
~Unit() {
if (!name) {
delete[] name;
name = NULL;
}
}
int GetSize() { return unitSize;}
int operator+(Unit right) { return unitSize + right.unitSize; }
int operator-(Unit right) { return unitSize - right.unitSize; }
int operator*(Unit right) { return unitSize * right.unitSize; }
};
class HUnit :public Unit {//자식클래스
public:
HUnit(): Unit(45, 125, 2, "HUnit") {}
};
void funcUnit(Unit a) {
cout << a.GetSize() << endl;
}
void funcHUnit(HUnit a) {
cout << a.GetSize() << endl;
}
int main() {
HUnit c1, c2;
cout << "Total Unit Size (+): " << c1 + c2 << "\n";
cout << "Total Unit Size (-): " << c1 - c2 << "\n";
cout << "Total Unit Size (*): " << c1 * c2 << "\n";
Unit a;
funcUnit(a);
//funcHUnit(a);
HUnit b;
funcUnit(b);
funcHUnit(b);
}
위 구문에서 funcHUnit(a)는 실행되지 않는다, HUnit이 Unit에게서 상속받아 HUnit은 Unit형에 포함되나 Unit이 HUnit형에 포함되지는 않기 때문이다.
• 오버로딩이 가능합니다.
• 모든 임베디드 연산자는 bool을 반환하고 대부분의 사용자 정의 오버로드도 bool을 반환하므로 사용자 정의 연산자는 임베디드 연산자와 동일한 방식으로 사용할 수 있습니다.
• 단, 사용자 정의 연산자 오버로딩에서는 모든 유형을 반환 유형(void 포함)으로 사용할 수 있습니다.
#include <iostream>
using namespace std;
class Unit {
private:
int hp;
public:
Unit() { hp = 0; }
Unit(int i) { hp = i; }
int GetHP() { return hp; }
int operator!=(Unit right);
};
int Unit::operator!=(Unit right) {
if (hp != right.hp) {
return 1;
}
return 0;
}
int main() {
Unit Unit1(10), Unit2(5), Unit3(5);
if (Unit1 != Unit2)
cout << "Unit1 != Unit2\n";
else
cout << "Unit1 == Unit2\n";
if (Unit2 != Unit3)
cout << "Unit2 != Unit3\n";
else
cout << "Unit2 == Unit3\n";
결과:
Unit1 != Unit2
Unit2 == Unit3
단항 연산자의 오버로딩
• 단항 연산자는 단일 피연산자에서 작동합니다.
– 입력 인수 없음 (postfix=후위표기식 ex)a++ 제외)
• 단항 연산자의 반환 유형에는 제한이 없습니다. 예를 들어 논리 NOT(!)가 정수값을 반환하는 것이 타당합니다.
• 오버로드할 수 있는 단항 연산자:
– ! (논리적 NOT), & (주소), ~ (보완), * (점수 삭제), + (단수 플러스), - (단수 부정), + + (증분), -- (감소), 변환 연산자
전위표기식 Unit1 = ++Unit3(1 더햊진 Unit3값을 Unit1에 넣기)와
후위표기식 Unit1 = Unit3++(Unit1에 Unit3값 넣고 Unit3을 ++)
는 표기법이 다르다
전위: Unit operator++()
후위: Unit operator++(int)
#include <iostream>
using namespace std;
class Unit {
private:
int hp;
public:
Unit() { hp = 0; }
Unit(int i) { hp = i; }
int GetHP() { return hp; }
Unit operator++() {
hp++;
return *this;
//Unit temp;
//temp.hp = ++hp;
//return temp;
};
Unit operator++(int) {
Unit temp;
temp.hp = hp++;
return temp;
}
};
int main() {
Unit Unit1, Unit2, Unit3(10);
Unit1 = Unit3++;
Unit2 = ++Unit3;
cout << Unit1.GetHP() << "\n";
cout << Unit2.GetHP() << "\n";
}
결과:
10
12
• 연산자는 friend 함수로 정의할 수 있습니다.
• 단항 연산자에 대한 인수 하나와 이항 연산자에 대한 인수 두 개입니다.
• 할당 연산자 '='은(는) friend 함수가 아닌 멤버 함수를 사용하여 오버로드될 수 있습니다.
//이항
Unit operator+(Unit left, Unit right){
}
//단항
Unit operator++(Unit left){
]
//단항, 후위식
Unit operator++(Unit left, int){
}
일반적으로 함수 선언할 때와 달리 좌측항의 값을 받는 인수가 하나씩 더 붙음
#include <iostream>
using namespace std;
class Unit {
private:
int hp;
public:
Unit() { hp = 0; }
Unit(int i) { hp = i; }
int GetHP() { return hp; }
friend Unit operator+(Unit left,Unit right);
};
Unit operator+(Unit left, Unit right) {
return left.hp + right.hp;
}
int main() {
Unit Unit1(10), Unit2(5), Unit3(5);
Unit3 = Unit1 + Unit2;
cout << "Unit3 : " << Unit3.GetHP() << endl;
}
Friend함수는 메서드 함수가 아니므로, this를 갖지 않는 만큼 left값도 받아와야 함!
할당문 왼쪽에 사용할 수 있습니다.
정적 변수를 반환합니다.
새 객체를 만들지 않습니다.
#include <iostream>
using namespace std;
double vals[] = { 1,2,3,4,5 };
double& setValues(int i) {
return vals[i];
}
int main() {
for (int i = 0; i < 5; i++)
cout << vals[i] << endl;
setValues(1) = 6;
for (int i = 0; i < 5; i++)
cout << vals[i] << endl;
}
객체 자체를 return하여 값을 바꿔줄 수 있어 단순히 value를 받아 scope내에서만 값을 바꿔주는 것과는 다르다.