Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
05-15 13:20
관리 메뉴

nomad-programmer

[Programming/C++] 연산자 오버로딩의 대한 예제 본문

Programming/C++

[Programming/C++] 연산자 오버로딩의 대한 예제

scii 2023. 6. 14. 02:00
// string1.h

#pragma once

#include <iostream>

using std::ostream;
using std::istream;


class String {
public:
// 생성자와 기타 메서드
    String(const char* s);              // 생성자
    String();                           // 디폴트 생성자
    String(const String& st);           // 복사 생성자
    ~String();                          // 소멸자
    int length() const { return len; } 
// 오버로딩 연산자 메서드
    String& operator=(const String& st);
    String& operator=(const char* s);
    char& operator[](const int i);
    const char& operator[](const int i) const;
// 오버로딩 연산자 프렌드 메서드
    friend bool operator<(const String& st1, const String& st2);
    friend bool operator>(const String& st1, const String& st2);
    friend bool operator==(const String& st1, const String& st2);
    friend ostream& operator<<(ostream& os, const String& st);
    friend istream& operator>>(istream& is, String& st);
// static 함수
    static int HowMany();

private:
    char* str;                      // 문자열을 지시하는 포인터
    int len;                        // 문자열의 길이
    static int num_strings;         // 객체의 수
    static const int CINLIM = 80;   // cin 입력 제한
};
// string1.cpp

#include <cstring>
#include "string1.h"

using std::cin;
using std::cout;

// static 클래스 멤버 초기화
int String::num_strings = 0;

// static 메서드
int String::HowMany() {
    return num_strings;
}

// 생성자
String::String(const char* s) {
    len = std::strlen(s);
    str = new char[len + 1];
    std::strcpy(str, s);
    num_strings++;
}

// 디폴트 생성자
String::String() {
    len = 2;
    str = new char[1];
    str[0] = '\0';
    num_strings++;
}

// 복사 생성자
String::String(const String& st) {
    num_strings++;
    len = st.len;
    str = new char[len + 1];
    std::strcpy(str, st.str);
}

// 소멸자
String::~String() {
    --num_strings;
    delete[] str;
}

String& String::operator=(const String& st) {
    if (this == &st) {
        return *this;
    }

    delete[] str;
    len = st.len;
    str = new char[len + 1];
    std::strcpy(str, st.str);
    return *this;
}

String& String::operator=(const char* s) {
    delete[] str;
    len = std::strlen(s);
    str = new char[len + 1];
    std::strcpy(str, s);
    return *this;
}

// const가 아닌 String에 읽기/쓰기 개별 문자 접근
char& String::operator[](const int i) {
    return str[i];
}

// const STring에 읽기 전용 개벌 문자 접근
const char& String::operator[](const int i) const {
    return str[i];
}

bool operator<(const String& st1, const String& st2) {
    return (std::strcmp(st1.str, st2.str) < 0);
}

bool operator>(const String& st1, const String& st2) {
    return st2 < st1;
}

bool operator==(const String& st1, const String& st2) {
    return (std::strcmp(st1.str, st2.str) == 0);
}

ostream& operator<<(ostream& os, const String& st) {
    os << st.str;
    return os;
}

istream& operator>>(istream& is, String& st) {
    char buffer[String::CINLIM];
    is.get(buffer, String::CINLIM);
    if (is) {
        st = buffer;
    }
    while (is && is.get() != '\n') {
        continue;
    }
    return is;
}

몇 개의 문자열을 입력할 수 있는 짧은 프로그램을 사용하여 String 클래스가 올바르게 동작하는지 테스트하는 코드이다. 가장 짧은 문자열이 어느것인지, 사전순으로 가장 앞에 나오는 것이 무엇인지 출력해준다.

#pragma warning(disable: 4996)

#include <iostream>
#include "string1.h"

using std::cout;
using std::cin;
using std::endl;

const int ARR_SIZE = 5;
const int MAX_LEN = 81;


int main(void) {
    String name;
    cout << "input english word " << ARR_SIZE << " (exit -> enter key)" << endl;
    
    String words[ARR_SIZE];
    char buffer[MAX_LEN]; 

    int i;
    for (i = 0; i < ARR_SIZE; i++) {
        cout << i + 1 << ": ";
        cin.get(buffer, MAX_LEN);
        while (cin && cin.get() != '\n') {
            continue;
        }
        if (!cin || buffer[0] == '\0') {
            break;
        }
        else {
            words[i] = buffer;
        }
    }

    int total = i;
    if (total > 0) {
        cout << "input words..." << endl;;
        for (i = 0; i < total; i++) {
            cout << words[i][0] << ": " << words[i] << endl;
        }

        int shortest = 0;
        int first = 0;
        for (i = 1; i < total; i++) {
            if (words[i].length() < words[shortest].length()) {
                shortest = i;
            }
            if (words[i] < words[first]) {
                first = 1;
            }
        }

        cout << "shorest words: " << words[shortest] << endl;
        cout << "first words: " << words[first] << endl;
        cout << "instances: " << String::HowMany() << endl;
    }
    else {
        cout << "no input!" << endl;
    }

    return 0;
}

// 결과
input english word 5 (exit -> enter key)
1: zoo
2: apple
3: saturday
4: banana
5: sky
input words...
z: zoo
a: apple
s: saturday
b: banana
s: sky
shorest words: zoo
first words: apple
instances: 6

static 클래스 멤버 함수

멤버 함수를 static으로 선언하는 것이 가능하다. (함수 정의와 함수 선언이 분리되어 있다면, 키워드 static은 함수 정의가 아니라 함수 선언에 나타나야 한다.) 이것은 두 가지 중요한 성질을 가지고 있다.

첫째, static 멤버 함수는 객체에 의해 호출될 필요가 없다. 사실, static 멤버 함수는 this 포인터도 갖지 않는다. static 멤버 함수가 public 부분에 선언되면, 그 함수는 클래스 이름과 사용 범위 결정 연산자를 사용하여 호출된다. String 클래스에 HowMany() 라는 static 멤버 함수를 제공할 수 있다. 그 멤버 함수는 다음과 같은 원형/정의를 클래스 선언에 가지고 있다.

static int HowMany() { return num_strings; }
// 이것은 다음과 같이 호출될 수 있다.
int count = String::HowMany();  // static 멤버 함수 호출

둘째, static 멤버 함수는 어떤 특정 객체와도 결합하지 않기 때문에, 사용할 수 있는 데이터 멤버는 static 데이터 멤버밖에 없다. 예를 들면, static 메서드 HowMany() 는 str나 len에는 접근할 수 없고, static멤버 num_strings에만 접근할 수 있다.

마찬가지로, static 멤버 함수를 사용하여, 클래스 인터페이스의 몇 가지 상황을 어떻게 처리할 것인지 제어하는, 클래스 사용 범위의 클래그(flag)를 설정할 수 있다. 예를 들면, 클래스의 내용을 출력하는 메서드가 사용할 출력 형식을 제어할 수 있다.

 

Comments