비교&관계 연산자 오버로딩

Jaemyeong Lee·2024년 8월 17일
0

FastCampusC++

목록 보기
61/78

이 코드는 C++에서 문자열을 다루기 위해 사용자 정의 String 클래스를 구현하고, 다양한 연산자 오버로딩을 통해 비교 및 논리 연산을 수행하는 예제입니다. 주석과 코드를 한 줄 한 줄 분석하여 자세하게 정리해보겠습니다.


1. String 클래스 정의 및 생성자

class String
{
private:
    char* _chars;

public:
    String(const char* chars) : _chars(new char[strlen(chars) + 1])
    {
        strcpy(_chars, chars);
    }
  • 클래스 멤버 변수:
    • char* _chars는 동적으로 할당된 문자열 데이터를 가리키는 포인터입니다.
  • 생성자:
    • 생성자는 const char* 타입의 문자열을 받아, 동적으로 메모리를 할당(new char[strlen(chars) + 1])하고, strcpy 함수를 사용하여 전달된 문자열을 _chars에 복사합니다.

2. operator== 오버로딩

    bool operator==(const String& s) const
    {
        return strcmp(_chars, s._chars) == 0;
    }
  • 비교 연산자 == 오버로딩:
    • String 객체를 비교하여, 문자열이 동일하면 true를, 그렇지 않으면 false를 반환합니다.
    • strcmp 함수는 두 문자열이 같으면 0을 반환하므로, 이를 사용하여 문자열을 비교합니다.

3. operator!= 오버로딩

    bool operator!=(const String& s) const
    {
        return !(*this == s);
    }
  • 비교 연산자 != 오버로딩:
    • operator==의 결과를 반전시켜 구현합니다. 즉, 두 문자열이 다르면 true를 반환합니다.
    • 이 오버로딩은 코드 재사용성을 높이기 위해 operator==를 활용합니다.

4. operator! 오버로딩

    bool operator!() const
    {
        return strlen(_chars) == 0;
    }
  • 논리 부정 연산자 ! 오버로딩:
    • 문자열이 빈 문자열("")이면 true를 반환합니다. 이는 문자열의 길이가 0인지를 검사하여 구현됩니다.

5. 비교 연산자 오버로딩 (<, >, <=, >=)

    bool operator<(const String& s) const
    {
        return strcmp(_chars, s._chars) < 0;
    }

    bool operator>(const String& s) const
    {
        return strcmp(_chars, s._chars) > 0;
    }

    bool operator<=(const String& s) const
    {
        return !(*this > s);
    }

    bool operator>=(const String& s) const
    {
        return !(*this < s);
    }
  • 비교 연산자 <, >, <=, >= 오버로딩:
    • <> 연산자는 strcmp 함수의 결과를 사용하여 구현됩니다. strcmp는 문자열을 사전순으로 비교합니다.
    • <=>= 연산자는 각각 >< 연산자를 재사용하여 구현됩니다.

6. operator|| 오버로딩

    bool operator||(bool b) const
    {
        return strlen(_chars) > 0 || b;
    }
  • 논리 OR 연산자 || 오버로딩:
    • 이 연산자는 문자열이 비어있지 않거나, 전달된 bool 값이 true이면 true를 반환합니다.
    • 그러나, 이와 같은 논리 연산자 오버로딩은 주의가 필요합니다. 단락 평가(Short-circuit evaluation)가 보장되지 않으며, 평가 순서도 예측할 수 없습니다. 이는 프로그램의 예상치 못한 동작을 초래할 수 있습니다.

7. 우주선 연산자 (<=>) 오버로딩

    strong_ordering operator<=>(const String& s) const
    {
        int result = strcmp(_chars, s._chars);
        if (result < 0)
        {
            return strong_ordering::less;
        }
        if (result > 0)
        {
            return strong_ordering::greater;
        }
        return strong_ordering::equal;
    }
  • 우주선 연산자 <=> 오버로딩:
    • 이 연산자는 C++20에서 도입된 비교 연산자입니다. strcmp의 결과를 사용하여 문자열의 순서를 비교합니다.
    • strong_ordering을 반환하여, 비교 결과가 less, greater, equal 중 하나로 나타나도록 합니다.

8. 전역 함수 operator== 오버로딩

    friend bool operator==(const char* s0, const String& s1);
bool operator==(const char* s0, const String& s1)
{
    return strcmp(s0, s1._chars) == 0;
}
  • 전역 함수 operator== 오버로딩:
    • 전역 함수로 const char*String 객체를 비교하는 연산자를 오버로딩합니다. 이 연산자는 strcmp 함수를 사용하여 두 문자열을 비교합니다.
    • 이 오버로딩은 String 객체와 C 스타일 문자열 간의 비교를 가능하게 합니다.

9. main 함수 분석

int main()
{
    String s0("abc");
    String s1("abc");

    if (s0 != s1)
    {
        cout << "Not Equal" << endl;
    }
    if (s0 < s1)
    {
        cout << "Less" << endl;
    }
    if (s0 > s1)
    {
        cout << "Greater" << endl;
    }
    if (s0 <= s1)
    {
        cout << "Less or Equal" << endl;
    }
    if (s0 >= s1)
    {
        cout << "Greater or Equal" << endl;
    }
    if ((s0 <=> s1) > 0)
    {
        cout << "Greater using <=> " << endl;
    }
    if ("b" == s0)
    {
        cout << "String comparison with char*" << endl;
    }

    String s("");
    if (!s) // 빈 문자열인지 확인
    {
        cout << "Empty string!" << endl;
    }

    if (s0 || func()) // 논리 연산자 오버로딩의 문제점
    {
        cout << "This will always execute func()" << endl;
    }

    return 0;
}
  • 비교 연산: s0s1의 문자열을 비교합니다. 두 문자열이 같으면 operator==가 true를 반환하고, !=, <, >, <=, >= 연산자들도 적절히 작동합니다.
  • 우주선 연산자 사용: <=> 연산자를 통해 문자열을 비교하고 그 결과에 따라 출력을 달리합니다.
  • 전역 operator== 테스트: "b" == s0은 C 스타일 문자열과 String 객체 간의 비교를 테스트합니다.
  • 논리 부정 연산자: if (!s)는 문자열이 빈 문자열인지 확인합니다.
  • 논리 연산자 오버로딩의 문제점: s0 || func()에서 func()가 실행되므로, 논리 연산자 오버로딩이 Short-circuit evaluation을 방해할 수 있습니다.

10. 주의사항 및 결론

  • 논리 연산자 오버로딩: 논리 연산자(&&, ||) 오버로딩은 단락 평가를 방해하고 평가 순서를 예측할 수 없게 만들기 때문에, 가능한 피해야 합니다.
  • 우주선 연산자 <=>: C++20의 우주선 연산자는 모든 비교 연산자를 하나로 통합할 수 있어 코드를 간결하게 만듭니다.
  • 메모리 관리: 생성자에서 동적으로 할당한 메모리를 소멸자에서 적절히 해제해야 메모리 누수를 방지할 수 있습니다. 예제에서는 소멸자가 구현되지 않았습니다.
  • 함수 이름 오타: 코드에서 strcmp 대신 strcpm으로 잘못 표기된 부분이 있습니다. 이러한 타이포는 컴파일 에러를 발생시키므로, 철자에 주의해야 합니다.

블로그 포스트 요약

이 코드는 C++에서 문자열을 다루기 위해 String 클래스를 구현하고, 다양한 연산자 오버로딩을 통해 문자열 비교 및 논리 연산을 수행하는 방법을 보여줍니다. 주요 개념은 다음과 같습니다:

  1. 연산자 오버로딩: `==

, !=, <, >, <=, >=, <=>, ||, !등의 연산자를 오버로딩하여String객체 간의 비교와 논리 연산을 구현합니다. 2. **논리 연산자 오버로딩의 문제점**:||&&연산자를 오버로딩하면 단락 평가가 제대로 작동하지 않으며, 평가 순서도 보장되지 않으므로 주의가 필요합니다. 3. **우주선 연산자<=>`: C++20에서 도입된 이 연산자는 비교 연산을 간단하게 처리할 수 있게 해줍니다.
4.
메모리 관리: 동적 메모리 할당과 해제를 적절히 관리해야 메모리 누수를 방지할 수 있습니다.
5.
타이포 주의**: 코드 작성 시 함수 이름이나 변수명에서의 오타는 컴파일 에러를 일으킬 수 있으므로 철저히 검토해야 합니다.

이 내용을 바탕으로 연산자 오버로딩과 관련된 주제를 블로그에 정리하여, C++에서 연산자 오버로딩을 효과적으로 사용하는 방법을 복습해보세요!

profile
李家네_공부방

0개의 댓글