산술 연산자 오버로딩

Jaemyeong Lee·2024년 8월 15일
0

FastCampusC++

목록 보기
60/78

이번 코드에서는 C++의 연산자 오버로딩을 통해 벡터 연산을 구현하는 방법과 friend 키워드를 사용한 특별한 함수 접근 방식을 다루고 있습니다. 이 내용을 한 줄 한 줄 분석하고 자세히 설명한 후, 블로그 포스트 형식으로 정리해드리겠습니다.


C++ 연산자 오버로딩 및 friend 키워드 사용 예제

연산자 오버로딩이란?

연산자 오버로딩은 C++에서 기존의 연산자(+, -, *, / 등)를 클래스의 멤버 함수나 비멤버 함수로 정의하여, 객체 간의 연산을 사용자 정의 방식으로 수행할 수 있게 하는 기능입니다. 예를 들어, 두 벡터 객체 간의 덧셈이나 뺄셈을 직접 구현할 수 있습니다.

코드 분석: Vector 클래스

먼저 Vector 클래스에서 정의된 다양한 연산자 오버로딩을 살펴보겠습니다.

class Vector
{
private:
    float x;
    float y;
    float z;
  • Vector 클래스는 x, y, z라는 세 개의 float 타입 멤버 변수를 가집니다.
  • 이 클래스는 3차원 벡터를 나타내며, 산술 연산 및 기타 연산자를 오버로딩하여 벡터 간의 연산을 수행합니다.

단항 연산자 오버로딩

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을 곱합니다.

VectorF와 VectorI 클래스 간의 연산

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의 비공개 멤버 변수에 접근할 수 있습니다. 이를 통해 VectorFVectorI의 값과 직접 연산할 수 있습니다.

메인 함수에서의 테스트

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 함수에서는 다양한 연산자 오버로딩을 테스트합니다.
  • 벡터 간의 덧셈, 뺄셈, 내적, 스칼라 곱셈, 나눗셈, 전위 및 후위 연산 등을 테스트합니다.
  • VectorFVectorI 클래스 간의 연산도 테스트하여, friend 관계를 확인합니다.

결론

이번 포스트에서는 C++에서의 연산자 오버로딩을 통해 벡터 연산을 구현하는 방법과 friend

키워드를 사용한 클래스 간 접근 제어에 대해 다루었습니다. 연산자 오버로딩은 객체 간 연산을 유연하게 구현할 수 있게 하며, friend 키워드는 특정 클래스에 비공개 멤버 접근을 허용하여 다양한 연산을 가능하게 합니다.

이러한 기술들은 객체 지향 프로그래밍에서 중요한 역할을 하며, 복잡한 연산을 단순화하고 코드의 가독성을 높이는 데 기여합니다. 이번 예제를 통해 C++의 강력한 기능을 잘 이해하고, 이를 실전 코드에 적용할 수 있기를 바랍니다.

profile
李家네_공부방

0개의 댓글