이번 코드에서는 C++의 연산자 오버로딩을 통해 벡터 연산을 구현하는 방법과 friend 키워드를 사용한 특별한 함수 접근 방식을 다루고 있습니다. 이 내용을 한 줄 한 줄 분석하고 자세히 설명한 후, 블로그 포스트 형식으로 정리해드리겠습니다.
friend 키워드 사용 예제연산자 오버로딩은 C++에서 기존의 연산자(+, -, *, / 등)를 클래스의 멤버 함수나 비멤버 함수로 정의하여, 객체 간의 연산을 사용자 정의 방식으로 수행할 수 있게 하는 기능입니다. 예를 들어, 두 벡터 객체 간의 덧셈이나 뺄셈을 직접 구현할 수 있습니다.
먼저 Vector 클래스에서 정의된 다양한 연산자 오버로딩을 살펴보겠습니다.
class Vector
{
private:
float x;
float y;
float z;
Vector 클래스는 x, y, z라는 세 개의 float 타입 멤버 변수를 가집니다.Vector operator+() const
{
return *this;
}
Vector operator-() const
{
return Vector{ -x, -y, -z };
}
operator+는 단항 + 연산자를 오버로딩합니다. 이 함수는 벡터를 그대로 반환합니다.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 };
}
float operator*(const Vector& v) const
{
return x * v.x + y * v.y + z * v.z;
}
Vector operator*(float v) const
{
return Vector{ x * v, y * v, z * v };
}
Vector operator/(float v) const
{
return Vector{ x / v, y / v, z / v };
}
operator+: 두 벡터 간의 덧셈을 수행하며, 각 성분끼리 더한 결과를 새로운 벡터로 반환합니다.operator-: 두 벡터 간의 뺄셈을 수행하며, 각 성분끼리 뺀 결과를 새로운 벡터로 반환합니다.operator* (Vector): 두 벡터 간의 내적(dot product)을 계산하여 float 타입의 값을 반환합니다. 내적은 두 벡터의 각 성분을 곱한 후 모두 더한 값입니다.operator* (float): 벡터와 스칼라 값을 곱하여 새로운 벡터를 반환합니다. 각 성분에 스칼라 값을 곱합니다.operator/: 벡터의 각 성분을 스칼라 값으로 나누어 새로운 벡터를 반환합니다.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;
}
++, --):operator++: 벡터의 각 성분을 1씩 증가시킨 후 자신을 반환합니다.operator--: 벡터의 각 성분을 1씩 감소시킨 후 자신을 반환합니다.++, --):operator++(int): 후위 증가 연산을 위한 오버로딩입니다. 현재 객체 상태를 저장한 후, 각 성분을 1씩 증가시키고 이전 상태를 반환합니다.operator--(int): 후위 감소 연산을 위한 오버로딩입니다. 현재 객체 상태를 저장한 후, 각 성분을 1씩 감소시키고 이전 상태를 반환합니다.friend 키워드를 사용한 비멤버 함수friend Vector operator*(float v0, const Vector& v1);
friend 키워드를 사용하여 operator* 함수가 Vector 클래스의 비공개 멤버 변수에 접근할 수 있도록 합니다.Vector operator*(float v0, const Vector& v1)
{
return Vector{ v0 * v1.x, v0 * v1.y, v0 * v1.z };
}
v0와 벡터 v1을 곱하여 새로운 벡터를 반환합니다. 이때 v1의 각 성분에 v0을 곱합니다.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 VectorI v) const
{
return VectorF{ x + v.x , y + v.y, z + v.z };
}
};
VectorF 클래스는 float 타입의 x, y, z 멤버를 가집니다.VectorI 타입의 벡터와 더할 수 있는 연산자를 오버로딩합니다.operator+는 VectorI 타입의 벡터와 VectorF를 더하여 새로운 VectorF 객체를 반환합니다.class VectorI
{
friend class VectorF;
private:
int x;
int y;
int z;
public:
VectorI(int x, int y, int z)
: x(x), y(y), z(z)
{
}
};
VectorI 클래스는 int 타입의 x, y, z 멤버를 가집니다.friend class VectorF로 선언되어 있어, VectorF 클래스는 VectorI의 비공개 멤버 변수에 접근할 수 있습니다. 이를 통해 VectorF는 VectorI의 값과 직접 연산할 수 있습니다.int main()
{
const Vector v0{ 0, 1, 2 };
const Vector v1{ 1, 2, 3 };
const Vector v2 = v0 + v1; // Vector v2 = v0.operator+(v1);
const Vector v3 = -v1; // Vector v3 = v1.operator-();
Vector v4 = +v0;
Vector v5 = -v0;
Vector v6 = v0 + v1;
Vector v7 = v0 - v1;
float v8 = v0 * v1;
Vector v9 = v0 * 3.0f;
Vector v10 = v0 / 3.0f;
Vector v11 = ++v10;
Vector v12 = v10++;
Vector v13 = --v10;
Vector v14 = v10--;
3.0f * v1; // Vector operator*(float v0, const Vector& v1) 호출
VectorF vf{ 0, 1, 2 };
VectorI vi{ 0, 1, 2 };
vf + vi;
}
main 함수에서는 다양한 연산자 오버로딩을 테스트합니다.VectorF와 VectorI 클래스 간의 연산도 테스트하여, friend 관계를 확인합니다.이번 포스트에서는 C++에서의 연산자 오버로딩을 통해 벡터 연산을 구현하는 방법과 friend
키워드를 사용한 클래스 간 접근 제어에 대해 다루었습니다. 연산자 오버로딩은 객체 간 연산을 유연하게 구현할 수 있게 하며, friend 키워드는 특정 클래스에 비공개 멤버 접근을 허용하여 다양한 연산을 가능하게 합니다.
이러한 기술들은 객체 지향 프로그래밍에서 중요한 역할을 하며, 복잡한 연산을 단순화하고 코드의 가독성을 높이는 데 기여합니다. 이번 예제를 통해 C++의 강력한 기능을 잘 이해하고, 이를 실전 코드에 적용할 수 있기를 바랍니다.