오버로딩이란 같은 일을 처리하는 함수를 매개변수의 형식을 달리하여 하나의 이름으로 작성할 수 있게 하는 것으로, 연산자 오버로딩은 하나의 연산자를 여러 의미로 사용할 수 있게 해준다.
함수 문법operator오버로딩할연산자(매개변수목록)
public에서 선언
우선 클래스안의 백터와 맴버함수를 public으로 선언하여 연산이 자유로울 때를 가정하여 연산자 오버로딩을 한다.
x, y, z로 이루어진 백터를 백터간에 사칙연산을 가능케하는 함수를 구성하고 백터간 뿐만 아니라 상수와도 연산이 가능하게 오버로딩을 하였다.
함수 문법클래스명 operator연산자(매개변수){ 연산 실행문 }
Vector operator*(const Vector& v) const {
return Vector{ x * v.x, y * v.y, z * v.z };
}
Vector operator/(const Vector& v) const {
return Vector{ x / v.x, y / v.y, z / v.z };
}
Vector operator+(const Vector& v) const {
return Vector{ x + v.x, y + v.y, z + v.z };
}
Vector operator-(const Vector& v) const {
return Vector{ x - v.x, y - v.y, z - v.z };
}
매개변수를 넣지 않아 함수를 호출한 인스턴스 하나만의 연산이 가능하게 하였다.
함수 문법클래스명 operator연산자(){ 연산 실행문 }
Vector operator-() const {
return Vector{ -x, -y, -z };
}
Vector operator+() const {
return *this;
}
Vector operator--() {
--x;
--y;
--z;
return *this;
}
Vector& operator++() {
++x;
++y;
++z;
return *this;
}
Vector operator--(int) { // 후위연산자는 자료형 매개변수를 넣어 전위와 구분해준다
Vector temp = *this;
--(*this);
return temp;
// 후위 연산자이기 때문에 연산은 하되, 연산하기 전의 원래값을 반환한다.
}
Vector& operator++(int) {
Vector temp = *this;
++(*this);
return temp;
}
백터간의 연산이 아닌 백터와 상수간의 연산을 실행 한다. 또한 상수가 함수를 호출할 순 없으므로 3 * 백터의 연산은 맴버함수가 아닌 전역함수로 따로 만들어준다
맴버 함수
Vector operator*(float f) const {
// 매개변수를 float으로 바꿔주어 오버로딩이 가능함
return Vector{ x * f, y * f, z * f };
}
전역함수
Vector operator*(float f, const Vector& v) {
// 5.0f.operator(v)는 불가 하기에 맴버 함수가 아닌 전역함수로 선언
return Vector{ v.x * f, v.y * f, v.z * f };
}
#include <iostream>
using namespace std;
class Vector {
public:
float x;
float y;
float z;
Vector operator*(const Vector& v) const {
return Vector{ x * v.x, y * v.y, z * v.z };
}
Vector operator*(float f) const {
// 매개변수를 float으로 바꿔주어 오버로딩이 가능함
return Vector{ x * f, y * f, z * f };
}
Vector operator/(const Vector& v) const {
return Vector{ x / v.x, y / v.y, z / v.z };
}
Vector operator+(const Vector& v) const {
return Vector{ x + v.x, y + v.y, z + v.z };
}
Vector operator-(const Vector& v) const {
return Vector{ x - v.x, y - v.y, z - v.z };
}
Vector operator-() const {
return Vector{ -x, -y, -z };
}
Vector operator+() const {
return *this;
}
Vector operator--() {
--x;
--y;
--z;
return *this;
}
Vector& operator++() {
++x;
++y;
++z;
return *this;
}
Vector operator--(int) {
// 후위연산자는 자료형 매개변수를 넣어 전위와 구분해준다
Vector temp = *this;
--(*this);
return temp;
// 후위 연산자이기 때문에 연산은 하되, 연산하기 전의 원래값을 반환한다.
}
Vector& operator++(int) {
Vector temp = *this;
++(*this);
return temp;
}
void print() {
cout << " x : " << x << " y : " << y << " z : " << z << endl;
}
};
Vector operator*(float f, const Vector& v) {
// 5.0f.operator(v)는 불가 하기에 맴버 함수가 아닌 전역함수로 선언
return Vector{ v.x * f, v.y * f, v.z * f };
}
int main() {
Vector v0{ 0, 1, 2 };
Vector v1{ 1, 2, 3 };
Vector v2 = v0 + v1; // v2 = v0.operator+(v1);와 같은 의미
Vector v3 = -v1; // v3 = v1.operator-();
Vector v4 = v0 / v1;
Vector v5 = v0 * v1;
Vector v6 = v0 * 3.0f;
Vector v7 = 5.0f * v0; // v7 = 5.0f
v0++;
--v1;
v1.print();
v1.print();
v2.print();
v3.print();
v4.print();
v5.print();
v6.print();
v7.print();
v0.print();
v1.print();
}
x : 0 y : 1 z : 2
x : 0 y : 1 z : 2
x : 1 y : 3 z : 5
x : -1 y : -2 z : -3
x : 0 y : 0.5 z : 0.666667
x : 0 y : 2 z : 6
x : 0 y : 3 z : 6
x : 0 y : 5 z : 10
x : 1 y : 2 z : 3
x : 0 y : 1 z : 2
위 예제에서는 백터의 값이 바뀌는것이 자유롭게 하기위해 public 안에서 백터와 맴버함수를 선언하였지만 클래스의 객체는 통상 private으로 선언하기에 이 때의 경우도 알아본다.
객체의 private 맴버는 해당 객체의 public 멤버 함수를 통해서만 접근할 수 있는데, 매번 새로운 public 멤버 함수를 작성하느 것은 매우 비효율적이기 때문에 friend를 사용한다.
friend는 지정한 대상에 한해 해당 객체의 모든 멤버에 접근할 수 있는 권한을 부여해주며 전역 함수, 클래스, 멤버 함수의 세가지 형태로 사용할 수 있다.
문법friend 클래스이름 함수이름(매개변수목록);
class VectorF; // Vector F 호출을 위해 전방선언이 필요함
class VectorI {
private:
float x;
float y;
float z;
public:
VectorI(float x, float y, float z)
: x(x), y(y), z(z) {
}
friend VectorF operator+(const VectorF& v0, VectorI& v1);
};
class VectorF {
private:
float x;
float y;
float z;
public:
VectorF(float x, float y, float z)
: x(x), y(y), z(z) {
}
friend VectorF operator+(const VectorF& v0, VectorI& v1);
};
VectorF operator+(const VectorF& v0, VectorI& v1) {
return VectorF(v0.x + v1.x, v0.y + v1.y, v0.z + v1.z);
}
전역 함수를 프렌드 함수로 선언하여 private 멤버에 접근 가능하게 하였다.
한 클래스가 다른 클래스의 private 멤버에 접근해야 한다면 클래스 자체를 프렌드로 선언하여 해당 클래스의 모든 멤버 함수가 특정 클래스의 프렌드가 되게끔 한다.
문법friend class 클래스이름;
class VectorI {
friend class VectorF;
private:
float x;
float y;
float z;
public:
VectorI(float x, float y, float z)
: x(x), y(y), z(z) {
}
};
class VectorF {
private:
float x;
float y;
float z;
public:
VectorF(float x, float y, float z)
: x(x), y(y), z(z) {
}
};
VectorF operator+(const VectorF& v0, VectorI& v1) {
return VectorF(v0.x + v1.x, v0.y + v1.y, v0.z + v1.z);
}
VectorF와 VectorI를 프랜드 클래스로 선언하여 전역 함수에서 VectorF와 VectorI의 private 멤버를 접근 가능하게 하였다.