이번 코드에서는 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++의 강력한 기능을 잘 이해하고, 이를 실전 코드에 적용할 수 있기를 바랍니다.