비트 연산자 오버로딩

Jaemyeong Lee·2024년 8월 19일
0

FastCampusC++

목록 보기
63/78

비트 연산자 오버로딩 예제 코드 분석

이 코드는 C++에서 비트 연산자 오버로딩을 사용하는 방법을 설명하는 예제입니다. 비트 연산자 오버로딩은 클래스 내부에서 객체의 데이터 멤버에 대해 비트 연산을 수행할 수 있도록 해줍니다. 이 코드에서는 3차원 벡터를 나타내는 Vector 클래스를 정의하고, 여러 비트 연산자 및 스트림 연산자(<<, >>)를 오버로딩하여 벡터 객체 간의 연산을 구현합니다.

코드 전체 분석 및 주석

#include <iostream>
#include <string>

using namespace std;

class Vector
{
private:
    int x;
    int y;
    int z;

public:
    Vector()
    {
        // 기본 생성자: 멤버 변수 x, y, z는 초기화되지 않은 상태로 남아있음
    }

    Vector(int x, int y, int z)
        :x(x), y(y), z(z)
    {
        // 매개변수를 받는 생성자: 입력된 x, y, z 값으로 멤버 변수를 초기화
    }

    // 출력 스트림 연산자 오버로딩
    friend ostream& operator<<(ostream& os, const Vector& v)
    {
        os << v.x << " " << v.y << " " << v.z;
        return os;
    }

    // 입력 스트림 연산자 오버로딩
    friend istream& operator>>(istream& is, Vector& v)
    {
        string temp; // 입력값을 임시로 받을 문자열 변수
        is >> temp;
        v.x = stoi(temp); // 문자열을 정수로 변환 후 x에 대입

        is >> temp;
        v.y = stoi(temp); // y에 대입

        is >> temp;
        v.z = stoi(temp); // z에 대입

        return is;
    }

    // 비트 NOT 연산자 오버로딩
    Vector operator~() const
    {
        // 각 멤버 변수에 대해 비트 NOT 연산을 수행
        return Vector(~x, ~y, ~z);
    }

    // 비트 AND 연산자 오버로딩
    Vector operator&(const Vector& v) const
    {
        // 대응되는 멤버 변수 간에 비트 AND 연산을 수행
        return Vector(x & v.x, y & v.y, z & v.z);
    }

    // 비트 OR 연산자 오버로딩
    Vector operator|(const Vector& v) const
    {
        // 대응되는 멤버 변수 간에 비트 OR 연산을 수행
        return Vector(x | v.x, y | v.y, z | v.z);
    }

    // 비트 XOR 연산자 오버로딩
    Vector operator^(const Vector& v) const
    {
        // 대응되는 멤버 변수 간에 비트 XOR 연산을 수행
        // 주의: z의 경우 v.z & v.z 연산을 하고 있음 (오타의 가능성 있음)
        return Vector(x ^ v.x, y ^ v.y, z & v.z);
    }

    // 왼쪽 시프트 연산자 오버로딩
    Vector operator<<(int v) const
    {
        // 각 멤버 변수에 대해 주어진 비트 수만큼 왼쪽으로 시프트
        return Vector(x << v, y << v, z << v);
    }

    // 오른쪽 시프트 연산자 오버로딩
    Vector operator>>(int v) const
    {
        // 각 멤버 변수에 대해 주어진 비트 수만큼 오른쪽으로 시프트
        return Vector(x >> v, y >> v, z >> v);
    }
};

int main()
{
    Vector v{ 1, 2, 3 };
    cout << v << endl; // operator<<(cout, v); - v의 값을 출력
    operator<<(cout, v).operator<<(endl); // 동일한 출력 방식

    cin >> v; // operator>>(cin, v) - 사용자로부터 입력을 받아 v에 값을 설정
    cout << v << endl; // 입력된 v의 값을 출력

    Vector v0{ 0, 0, 0 };
    cout << ~v0 << endl; // v0에 대한 비트 NOT 연산의 결과를 출력

    Vector v1{ 1, 2, 3 };
    cout << (v0 & v1) << endl; // v0과 v1의 비트 AND 연산 결과를 출력
    cout << (v0 | v1) << endl; // v0과 v1의 비트 OR 연산 결과를 출력
    cout << (v1 ^ v1) << endl; // v1과 v1의 비트 XOR 연산 결과를 출력

    Vector v2{ 2, 4, 8 };
    cout << (v2 << 2) << endl; // v2의 각 성분을 2비트 왼쪽으로 시프트한 결과를 출력
    cout << (v2 >> 2) << endl; // v2의 각 성분을 2비트 오른쪽으로 시프트한 결과를 출력
}

각 연산자에 const가 사용된 이유

여기에서 각 연산자 오버로딩 함수가 const로 선언된 이유는, 해당 함수들이 멤버 변수를 수정하지 않고, 오직 읽기만 하기 때문입니다.

  • const 사용의 중요성:
    • 코드의 안전성: 연산자 오버로딩 함수에 const를 붙이면, 해당 함수가 클래스 멤버 변수를 변경하지 않음을 보장합니다. 이렇게 하면, 불필요한 변수 변경을 방지하여 코드의 안정성을 높일 수 있습니다.
    • const 객체에 대한 연산 지원: 함수가 const로 선언되지 않으면, const 객체에 대해 해당 연산을 수행할 수 없습니다. 예를 들어, const Vector v{1, 2, 3};로 선언된 객체에서 비트 연산을 수행하려면, 연산자 오버로딩 함수가 const로 선언되어 있어야 합니다.

마무리

이 예제는 C++에서 비트 연산자를 오버로딩하여 사용자 정의 데이터 타입 간에 비트 연산을 구현하는 방법을 보여줍니다. 특히 const를 사용하여 멤버 변수를 변경하지 않는 연산임을 명시함으로써, 코드의 신뢰성과 안정성을 높였습니다. 이를 통해 비트 연산이 필요한 다양한 상황에서 객체 지향적으로 접근할 수 있습니다.

이 예제는 벡터와 같은 복잡한 데이터 구조에서 비트 연산을 효과적으로 수행하는 방법을 보여주며, C++의 연산자 오버로딩을 이해하는 데 큰 도움이 됩니다.

profile
李家네_공부방

0개의 댓글