이 코드는 C++에서 첨자 연산자([]
)를 오버로딩하여 사용자 정의 타입을 배열처럼 접근할 수 있도록 하는 예제입니다. 여기에서는 Vector
, String
, HashTable
클래스를 정의하여 각각의 특성에 맞게 첨자 연산자를 오버로딩하는 방법을 보여줍니다.
Vector
클래스 분석class Vector
{
public:
float x, y, z;
Vector(float x, float y, float z)
: x(x), y(y), z(z)
{
}
float& operator[](int index)
{
if (index < 1)
return x;
if (index < 2)
return y;
return z;
}
float operator[](int index) const
{
if (index < 1)
return x;
if (index < 2)
return y;
return z;
}
};
클래스 개요:
Vector
클래스는 3차원 벡터를 나타내며, 멤버 변수로 x
, y
, z
를 가지고 있습니다.Vector
객체를 배열처럼 인덱스로 접근할 수 있게 합니다.첨자 연산자 오버로딩:
float& operator[](int index)
: Vector
객체의 멤버 변수에 대한 참조를 반환합니다. 즉, 인덱스로 값을 읽고 쓸 수 있습니다.x
를, 2 미만이면 y
를, 그 외는 z
를 반환합니다.float operator[](int index) const
:const
객체에 대해 호출되며, 멤버 변수를 변경하지 않고 값을 반환합니다.const
객체에서도 배열처럼 인덱스 접근을 지원합니다.String
클래스 분석class String
{
private:
char* _chars;
public:
String(const char* chars)
: _chars(new char[strlen(chars) + 1])
{
strcpy(_chars, chars);
}
~String()
{
delete[] _chars;
}
char operator[](int index) const
{
return _chars[index];
}
char& operator[](int index)
{
return _chars[index];
}
friend std::ostream& operator<<(std::ostream& os, const String& s)
{
os << s._chars;
return os;
}
};
클래스 개요:
String
클래스는 C 스타일 문자열을 관리합니다. 동적으로 할당된 char
배열을 관리하며, 소멸자를 통해 메모리 해제를 책임집니다.첨자 연산자 오버로딩:
char operator[](int index) const
:const
객체에 대해 호출되며, 해당 인덱스의 문자를 반환합니다.char& operator[](int index)
:String
객체의 특정 인덱스에 있는 문자의 참조를 반환하여, 해당 문자를 수정할 수 있게 합니다.추가 연산자 오버로딩:
friend std::ostream& operator<<(std::ostream& os, const String& s)
:String
객체를 출력 스트림(std::cout
)에 출력할 수 있도록 지원합니다.Bucket
클래스 분석class Bucket
{
private:
std::vector<KeyValue> _items;
public:
Value& get(const Key& key)
{
for (KeyValue& keyValue : _items)
{
if (keyValue.first == key)
{
return keyValue.second;
}
}
_items.push_back(std::make_pair(key, Value()));
return _items.back().second;
}
};
클래스 개요:
Bucket
클래스는 키-값 쌍(Key-Value pair)을 저장하는 컨테이너로, 내부적으로 std::vector
를 사용합니다.get
메서드를 통해 키에 해당하는 값을 찾거나, 존재하지 않으면 새로운 키-값 쌍을 추가합니다.get
메서드:
Key
와 Value
는 각각 std::string
으로 정의된 별칭입니다.HashTable
클래스 분석class HashTable
{
private:
std::vector<Bucket> _buckets;
int hash(const Key& key) const
{
int h = 0;
for (char ch : key)
{
h += ch;
}
return h;
}
public:
HashTable(int size = 100)
: _buckets(std::vector<Bucket>(size))
{
}
Value& operator[](const Key& key)
{
int bucketIndex = hash(key) % _buckets.size();
Bucket& bucket = _buckets[bucketIndex];
return bucket.get(key);
}
};
클래스 개요:
HashTable
클래스는 키-값 쌍을 저장하는 해시 테이블을 구현합니다. 내부적으로 std::vector
를 사용하여 버킷을 관리하며, 각 버킷은 Bucket
객체입니다.해시 함수:
hash
메서드는 키 문자열을 받아 해시 값을 계산합니다. 여기서는 각 문자의 ASCII 값을 더하여 해시 값을 구합니다.첨자 연산자 오버로딩:
Value& operator[](const Key& key)
:Bucket
을 선택하기 위해 해시 함수의 결과를 사용하며, 선택된 Bucket
객체의 get
메서드를 통해 값을 찾습니다.string
, hashtable
, vector
의 관계첨자 연산자 ([]
):
String
클래스와 첨자 연산자:
String
클래스에서 첨자 연산자를 통해 문자열의 특정 문자를 읽거나 수정할 수 있습니다. 이는 C 스타일의 문자열 접근 방식과 유사합니다.HashTable
클래스와 첨자 연산자:
HashTable
클래스에서는 키를 인덱스로 사용하여 값에 접근합니다. 해시 함수는 주어진 키를 해시값으로 변환하고, 그 값을 이용해 적절한 버킷을 선택합니다. 해당 버킷에서 키-값 쌍을 찾고, 그 값을 반환하거나 수정할 수 있게 합니다.vector
와 첨자 연산자:
std::vector
는 내부적으로 첨자 연산자를 사용하여 요소에 접근합니다. Bucket
클래스에서 std::vector<KeyValue>
를 사용하여 키-값 쌍을 저장하며, vector
의 첨자 연산자를 활용해 해당 쌍에 접근합니다.이 예제는 C++에서 첨자 연산자 오버로딩을 통해 사용자 정의 타입을 배열처럼 접근할 수 있도록 하는 방법을 보여줍니다. Vector
, String
, HashTable
클래스는 각각의 데이터 타입에 맞는 첨자 연산자 오버로딩을 통해 유연한 데이터 접근을 지원합니다. 이 기법은 클래스 객체를 더욱 직관적으로 사용할 수 있게 하며, 특히 복잡한 데이터 구조를 처리할 때 유용합니다.
블로그 포스트에서 이 내용을 정리할 때는 각 클래스의 특징과 첨자 연산자의 역할을 강조하고, 왜 이러한 설계가 필요한지를 설명하면 좋습니다. 이를 통해 독자들이 C++의 연산자 오버로딩 개념을 깊이 이해하고, 실제 코드에 적용할 수 있게 될 것입니다.