Home [C++ 프로그래밍] 9강 - 연산자 다중 정의
Post
Cancel

[C++ 프로그래밍] 9강 - 연산자 다중 정의

💡해당 게시글은 방송통신대학교 이병래 교수님의 'C++ 프로그래밍' 강의를 개인 공부 목적으로 메모하였습니다.



학습 개요


  • 복사와 이동을 용도에 맞게 활용할 수 있는 대입 및 이동 대입 연산자의 다중 정의에 대하여 학습함
  • 두 가지 클래스의 예를 통하여 연산자 다중 정의를 적용해봄
  • 먼저 배열을 표현하는 클래스를 통해 첨자를 통해 객체의 데이터를 액세스하기 위한 연산자를 구현하여 본 후, 문자열을 표현하기 위한 클래스를 구현해 봄
  • C++의 표준 라이브러리에는 문자열을 보다 편리하게 사용할 수 있게 하는 string이라는 클래스를 제공하고 있는데, string 클래스와 유사한 처리를 할 수 있는 클래스를 직접 만들어 보면서, 그 과정에서 다양한 연산자를 다중 정의해 볼 것임
  • 이 과정에서 자료형의 변환 연산자를 정의하는 방법도 함께 살펴볼 것임



학습 목표


  • 대입 및 이동 대입 연산자를 필요에 맞게 다중 정의할 수 있음
  • 배열 첨자 연산자를 다중 정의할 수 있음
  • 문자열을 처리하기 위한 여러 가지 연산자를 다중 정의할 수 있음
  • 자료형을 변환하는 연산자를 다중 정의할 수 있음



주요 용어


  • 이동 대입 연산자
    • 좌측 피 연산자에 대입할 우측 피 연산자가 rvalue일 때 우측 피 연산자의 내용을 좌측 피 연산자로 이동하는 대입 연산자



강의록


대입 및 이동 대입 연산자

대입 연산자의 다중 정의

  • 대입 연산자 (=)
    • 묵시적인 대입 연산자
      • 우측 피 연산자 데이터 멤버를 좌측 피 연산자에 그대로 복사함
    • 객체에 동적 할당 된 메모리를 가리키는 포인터가 포함되어 있을 경우 얕은 복사로 인해 의도하지 않은 공유 상태의 문제가 발생할 수 있음
    • 깊은 복사를 할 수 있는 대입 연산자를 다중 정의할 필요가 있음
  • VecF 클래스의 대입 연산자 다중 정의

    1
    2
    3
    4
    5
    6
    7
    8
    
      VecF& VecF::operator=(const VecF& fv) {
        if (n != fv.n) { // 벡터의 크기가 다르다면
          delete[] arr; // 기존 메모리를 반환하고
          arr = new float[n = fv.n];  // 새로 메모리를 할당함
        }
        memcpy(arr, fv.arr, sizeof(float)*n); // 데이터 복사
        return *this; // 자기 자신을 참조로 돌려줌
      }
    

이동 대입 연산자의 다중 정의

  • 이동 대입 연산자 (=)
    • 좌측 피 연산자에 대입 할 우측 피 연산자가 rvalue일 때 사용됨
      • 대입 후 우측 피 연산자의 내용이 더 이상 필요 없는 상황
    • 우측 피 연산자의 내용을 좌측 피 연산자로 이동하여 불필요한 복사를 피함으로써 효율성을 높일 수 있음
  • VecF 클래스의 이동 대입 연산자 다중 정의

    1
    2
    3
    4
    5
    6
    7
    
      VecF& VecF::operator=(VecF&& fv) { // 임시로 만들어진 VecF 객체와 자원을 이동
        delete[] arr; // 기존 메모리를 반환하고
        n = fv.n; // 우측 피 연산자의 내용을 이동함
        arr = fv.arr;
        fv.arr = nullptr; // nullptr로 바꿔 fv가 배열을 가리키지 않도록 함
        return *this;
      }
    

대입 및 이동 대입 연산자의 활용

  • VFMain3.cpp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
      #include <iostream>
      using namespace std;
        
      int main() {
        float a[3] = { 1, 2, 3 };
        float b[3] = { 2, 4, 6 };
        VecF v1(3, a);
        VecF v2(3, b);
        VecF v3(3);
        
        // 대입 연산자 (l-value를 사용한 깊은 복사)
        v3 = v1; // 복사 대입 연산자 호출
        cout << v3 << endl;
        
        // 이동 대입 연산자 (r-value를 사용한 이동)
        v3 = v1.add(v2); // v1과 v2를 더한 결과를 새로 만들어 임시 객체로 반환
        cout << v1 << " + " << v2 << " = " << v3 << endl;
        
        return 0;
      }
        
      // [ 1 2 3 ]
      // [ 1 2 3 ] + [ 2 4 6 ] = [ 3 6 9 ]
    
  • 복사 대입

    image.png

  • 이동 대입

    image.png

    image.png

    • 이동 대입에서는 v1.add(v2)로 생성된 임시 객체의 메모리 소유권이 v3로 효율적으로 이동 됨

std::move함수의 활용

  • 두 VecF 객체를 교환하는 함수의 구현
    • 아래 swapVecF함수는 대입 연산자를 사용하므로 비효율적인 복사가 두 번 발생함

      1
      2
      3
      4
      5
      
        void swapVecF(VecF& v1, VecF& v2) {
          VecF tmp(v1); // 복사 생성
          v1 = v2; // 대입 연산자 사용
          v2 = tmp; // 대입 연산자 사용
        }
      
      1
      2
      3
      4
      5
      6
      7
      8
      
        int main() {
          float a[3] = { 1, 2, 3 };
          float b[3] = { 2, 4, 6 };
          VecF vec1(3, a);
          VecF vec2(3, b);
          swapVecF(vec1, vec2);
                  
        }
      

      image.png

  • std::move함수
    • 인수로 전달되는 객체의 rvalue 참조를 반환
      • lvalue를 rvalue처럼 사용할 수 있게 함
      • 이동 생성자나 이동 대입 연산자를 강제로 호출할 수 있음
    • VecF tmp = std::move(v1);
      • v1의 rvalue 참조를 구하여 tmp의 초기화에 사용
      • 이동 생성자를 이용하여 tmp 생성
    • v1 = std::move(v2);
      • v2의 rvalue 참조를 구하여 v1에 대입
      • 이동 대입 연산자 실행
  • 두 VecF 객체를 교환하는 함수의 구현 - std::move 활용
    • std::move를 사용하면 불필요한 데이터 복사 없이 포인터의 교환만으로 함수를 구현할 수 있어 효율적임
    1
    2
    3
    4
    5
    
      void swapVecF(VecF& v1, VecF& v2) {
        VecF tmp = move(v1); // 이동 생성자
        v1 = move(v2); // 이동 대입 연산자 사용
        v2 = move(tmp); // 이동 대입 연산자 사용
      }
    
    1
    2
    3
    4
    5
    6
    7
    8
    
      int main() {
        float a[3] = { 1, 2, 3 };
        float b[3] = { 2, 4, 6 };
        VecF vec1(3, a);
        VecF vec2(3, b);
        swapVecF(vec1, vec2);
            
      }
    

    image.png

    image.png

    image.png

    image.png

    image.png

    • 실행 과정
      1. VecF tmp = move(v1);
        • tmpv1의 데이터 소유권을 이전 받음
        • v1의 포인터는 nullptr가 됨
      2. v1 = move(v2);
        • v1v2의 데이터 소유권을 이전 받음
        • v2의 포인터는 nullptr가 됨
      3. v2 = move(tmp);
        • v2tmp의 데이터 소유권을 이전 받음
        • tmp의 포인터는 nullptr가 됨
      4. 결과적으로 v1v2의 내용물이 효율적으로 교환 됨

[]연산자의 다중 정의

SafeIntArray클래스

  • 요구 사항
    • 배열처럼 지정 된 개수의 int 값을 저장할 수 있음

      1
      
        SafeIntArray a(10); // 10개의 int 값을 저장하는 객체
      
    • 각각의 값들은 0번부터 시작하는 일련 번호를 첨자로 지정하여 액세스함

      1
      
        a[5] = 10; // 6번째 위치에 10을 저장함
      
    • 첨자가 지정 된 범위를 벗어날 경우 오류 메시지를 출력한 후 프로그램을 종료함

      1
      
        cout << a[11]; // 범위를 벗어나므로 오류 발생
      

[]연산자의 다중 정의

  • []연산자
    • 배열의 첨자를 지정하는 이항 연산자
    • 피 연산자
      • 배열첨자
  • 데이터를 저장하기 위해 사용할 [] 연산자

    1
    2
    
      SafeIntArray a(10);
      a[5] = 10; // a -> *this, 5 -> i 
    
    1
    2
    3
    4
    
      // SafeIntArray 클래스 내부
      int& SafeIntArray::operator[](/assets/img/knou/cpp/2025-06-23-knou-cpp-9/int i) { // 정수 변수의 참조를 반환하기 때문에 a(n)의 값을 직접 바꾸거나 읽을 수 있음
        return arr[i]; // *this 객체의 멤버인 배열의 원소를 참조로 반환
      }
    

[]연산자의 다중 정의

  • const객체를 위한 []연산자
    • 데이터를 읽기만 할 수 있도록 []연산자를 정의
      • const로 선언된 객체는 내부 데이터를 변경할 수 없으므로, 데이터를 읽기만 하는 const멤버 함수만 호출할 수 있음
      • const객체에 대해 []연산자를 사용하려면 const버전의 operator[]를 별도로 정의(다중 정의)해야 함
      1
      2
      3
      4
      
        void f(const SafeIntArray& x) { // x가 const이기 때문에 값을 바꿀 수 없음
          for (int i=0; i < x.size(); i++)
            cout << x[i] << endl; // []는 x의 값을 수정할 수 있는 연산자임 -> 에러 발생
        }
      
      1
      2
      3
      
        // int& SafeIntArray::operator[](/assets/img/knou/cpp/2025-06-23-knou-cpp-9/int i) { // const가 아닌 operator[]는 멤버를 수정할 수 있는 int&를 반환하므로 const 객체에 대해 호출될 수 없음
              
        // } 
      
      1
      2
      3
      
        int SafeIntArray::operator[](/assets/img/knou/cpp/2025-06-23-knou-cpp-9/int i) const { // const 한정자를 붙이고 값을 반환(l-value가 아닌)하도록 operator[]를 다중 정의
              
        }
      

SafeIntArray.h

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
32
33
34
35
36
37
#include <iostream>

class SafeIntArray {
  int limit;      // 원소의 개수
  int *arr;       // 데이터 저장 공간
public:
  // 생성자
  SafeIntArray(int n) : limit(n) {
    arr = new int[n]; // 공간 할당
  }
  
  // 소멸자
  ~SafeIntArray() {
    delete[] arr; // 공간 반환 
  }
  
  // 배열의 크기를 반환
  int size() const { return limit; }

  // l-value로 사용될 수 있는 operator[] (non-const 객체용)
  int& operator[](/assets/img/knou/cpp/2025-06-23-knou-cpp-9/int i) { // i번 원소를 반환하는 멤버 함수
    if(i < 0 || i >= limit) {
      std::cout << "첨자가 범위를 벗어나 프로그램을 종료합니다.";
      exit(EXIT_FAILURE);
    }
    return arr[i]; // i번 원소 반환
  }

  // r-value로 사용될 수 있는 operator[] (const 객체용)
  int operator[](/assets/img/knou/cpp/2025-06-23-knou-cpp-9/int i) const {
    if(i < 0 || i >= limit) {
      std::cout << "첨자가 범위를 벗어나 프로그램을 종료합니다.";
      exit(EXIT_FAILURE);
    }
    return arr[i]; // i번 원소 반환
  }
};

SafeArr.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include "SafeIntArray.h"
using namespace std;

int main()
{
  SafeIntArray a(10); // 10개의 원소를 갖는 객체 생성

  for (int i = 0; i < 10; i++)
    a[i] = i;

  cout << a[5] << endl;   // 올바른 범위의 원소 액세스
  cout << a[12] << endl;  // 범위를 벗어난 액세스

  return 0;
}

문자열 클래스

C 스타일 문자열

  • 문자열의 저장
    • 문자열의 끝을 알리기 위해 널(null) 문자('\0')를 사용함
      • Null-terminated string
    • 문자열을 저장하기 위한 char형 배열

      1
      
        char str1[40] = "C style string";
      

      image.png

      1
      
        char str2[] = "Object-Oriented ";
      

      image.png

    • 문자열 리터럴

      1
      
        const char* str3 = "Programming";
      

      image.png

  • C 스타일 문자열 처리 함수 (헤더 파일: #include <cstring>)
    • 문자열의 길이 구하기

      1
      
        size_t strlen(const char* str);
      
      • n = strlen("abcde");n = 5
        • 널 문자는 길이에 포함되지 않음
    • 문자열 복사하기

      1
      
        char* strcpy(char* strDestination, const char* strSource);
      
      1
      2
      
        char str1[10] = "KNOU";
        strcpy(str1, "CS");
      

      image.png

    • 문자열 연결하기

      1
      
        char* strcat(char* strDestination, const char* strSource);
      
      1
      2
      
        char str2[10] = "KNOU";
        strcat(str2, "CS");
      

      image.png

MyString클래스

  • 요구 사항
    • 문자열을 저장하되 다음의 다중 정의된 연산자를 포함하며, 실행 시 필요에 따라 저장 공간을 늘릴 수 있음

      연산자기능
      =대입 연산자, C 스타일 문자열이나 MyString 객체를 복사함
      +문자열 연결 연산자, 두 문자열을 연결한 문자열을 구힘
      +=문자열을 뒤에 추가함
      ==, >, <관계 연산자, 두 문자열의 등호 및 순서를 비교함
      <<스트림 출력 연산자, 출력 스트림으로 문자열을 출력함
      []문자열 내의 개별 문자 접근
    • 생성자 및 소멸자

      1
      
        MyString();
      
      1
      
        MyString(const char* str);
      
      1
      
        MyString(const MyString& mstr);
      
      1
      
        MyString(MyString&& mstr);
      
      1
      
        MyString(int s); // private - 내부용으로만 사용함
      
      1
      
        ~MyString();
      
    • 기타 메소드

      1
      
        int length() const; // 문자열 길이 반환
      
    • 데이터 멤버

      데이터 멤버용도
      int len문자열의 길이를 저장함
      int bufSize최대로 저장할 수 있는 문자열의 길이를 저장함
      char* buf문자열 저장 공간

MyString.h

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
32
33
34
35
36
37
#include <iostream>

class MyString {
  int len; // 문자열의 길이
  int bufSize; // 저장 가능한 문자열의 길이
  char* buf;
  MyString(int s); // 생성자(private)
public:
  MyString(); // 디폴트 생성자
  MyString(const char* str); // 생성자
  MyString(const MyString& mstr); // 복사 생성자
  MyString(MyString&& mstr); // 이동 생성자
  ~MyString(); // 소멸자
  int length() const; // 문자열 길이 반환 메소드

  // --- 연산자 다중 정의 ---
  MyString& operator=(const MyString& mstr); // 대입 연산자
  MyString& operator=(MyString&& mstr); // 이동 대입 연산자
  MyString operator+(const MyString& mstr) const; // 문자열 연결 연산자
  MyString& operator+=(const MyString& mstr); // 문자열 추가 연산자
  bool operator==(const MyString& mstr) const; // == 연산자
  bool operator>(const MyString& mstr) const; // > 연산자
  bool operator<(const MyString& mstr) const; // < 연산자
  char& operator[](/assets/img/knou/cpp/2025-06-23-knou-cpp-9/int i); // [] 연산자
  char operator[](/assets/img/knou/cpp/2025-06-23-knou-cpp-9/int i) const; // const [] 연산자

  // 스트림 출력 연산자 (friend 함수로 선언)
  friend std::ostream& operator<<(std::ostream& os, const MyString& mstr); // 외부 함수나 클래스가 클래스 내부에 접근 가능
};

// 스트림 출력 연산자 구현 (inline)
inline std::ostream& operator<<(std::ostream& os, const MyString& mstr)
{
  os << mstr.buf;
  return os;
}

MyString.cpp

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <cstring>
#include "MyString.h"

// private 생성자
MyString::MyString(int s) : len(s), bufSize(s + 1) { // 멤버 변수 값 선언 시 초기화
  buf = new char[s + 1];
  buf[s] = '\0';
}

// 디폴트 생성자
MyString::MyString() : len(0), bufSize(1) {
  buf = new char[1];
  buf[0] = '\0';
}

// 생성자
MyString::MyString(const char* str) {
  len = bufSize = strlen(str); // 문자열 길이
  buf = new char[len + 1]; // 문자열 저장 공간 할당
  strcpy(buf, str); // 문자열 복사
}

// 복사 생성자
MyString::MyString(const MyString& mstr) : len(mstr.len), bufSize(mstr.len) {
  buf = new char[len + 1];
  strcpy(buf, mstr.buf);
}

// 이동 생성자
MyString::MyString(MyString&& mstr) : len(mstr.len), bufSize(mstr.bufSize), buf(mstr.buf) {
  mstr.buf = nullptr;
}

// 소멸자
MyString::~MyString() {
  delete[] buf;
}

// 문자열 길이 반환 메소드
int MyString::length() const {
  return len;
}

// 대입 연산자
MyString& MyString::operator=(const MyString& mstr) {
  if (bufSize < mstr.len) { // 문자열 공간이 필요량보다 작으면
    delete[] buf; // 기존 공간 반환
    len = bufSize = mstr.len; // 새로운 문자열의 길이
    buf = new char[len + 1]; // 새로운 공간 할당
  } else { // 그렇지 않으면
    len = mstr.len; // 문자열의 길이만 수정
  }
  strcpy(buf, mstr.buf);
  return *this;
}

// 이동 연산자
MyString& MyString::operator=(MyString&& mstr) {
  delete[] buf;
  len = mstr.len;
  bufSize = mstr.bufSize;
  buf = mstr.buf;
  mstr.buf = nullptr;
  return *this;
}

// 문자열 연결 연산자
MyString MyString::operator+(const MyString& mstr) const {
  MyString tmstr(len + mstr.len); // private으로 정의한 생성자
  strcpy(tmstr.buf, buf);
  strcpy(tmstr.buf + len, mstr.buf);
  return tmstr;
}

MyString& MyString::operator+=(const MyString& mstr) {
  if (bufSize < len + mstr.len) {
    char* tbuf = new char[bufSize = len + mstr.len + 1];
    strcpy(tbuf, buf);
    delete[] buf;
    buf = tbuf;
  }
  strcpy(buf + len, mstr.buf);
  len += mstr.len;
  return *this;
}
1
2
3
4
5
6
7
8
char cstr1[10] = "C string";
char cstr2[10];
char* cstr3;
MyString mstr1("MyString 객체");
MyString mstr2;
// cstr2 = cstr1; // 에러
cstr3 = cstr1; // 포인터 복사
mstr2 = mstr1; // deep copy

MSMain.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main() {
  MyString str1("MyString class");
  MyString str2("Object Oriented ");
  MyString str3;

  cout << str1 << endl; // 문자열 출력
  str3 = "Programming"; // 묵시적 형 변환 및 이동 대입
  cout << str3 << "의 문자열 길이는 ";
  cout << str3.length() << endl; // 문자열 길이를 구하는 메소드
  str1 = str2; // 대입 연산자로 문자열 복사
  cout << str1 << endl;
  str1 = str1 + str3; // 문자열 연결 연산자, 이동 대입 연산자
    
}

string

  • string이란?
    • 문자열을 저장하기 위한 표준 C++ 라이브러리의 클래스

      1
      
        basic_string<char>
      
    • 헤더 파일

      1
      
        #include <string>
      
    • 연산자
      • [], +, +=, =, ==, !=, >, >=, <, <=, 스트림 입출력(<<, >>) 등
    • 멤버 함수
      • length, append, find, c_str
    • 함수
      • stoi, stod, to_string, swap, getline

자료형의 변환

묵시적 형 변환

  • MyString 클래스의 묵시적 형 변환

    1
    2
    
      str3 = "Programming"; // 묵시적 변환 (자동)
      str3 = MyString("Programming"); // 명시적 객체 생성
    
    1
    2
    
      MyString& operator=(const MyString& mstr); // 복사 대입 연산자
      MyString& operator=(MyString&& mstr); // 이동 대입 연산자
    
    • MyString("Programming")은 임시 객체 → rvalue
      • MyString&&이동 대입 연산자가 호출 됨

    image.png

형 변환 연산자를 정의하는 위치

  1. 값을 제공하는 송신 측 클래스에서 정의하는 방법
    • 값을 받는 수신 측 클래스의 이름으로 연산자를 정의함
      • MyString 클래스의 객체를 C 스타일 문자열로 변환하기

        1
        2
        3
        4
        5
        6
        7
        8
        
          class MyString {
                    
            operator char*() const {
              char* pt = new char[length()+1];
              strcpy(pt, buf);
              return pt;
            }
          };
        
  2. 값을 제공 받는 수신 측 클래스에서 정의하는 방법
    • 송신 측 클래스의 객체를 인수로 받는 1인수 생성자를 정의함

      1
      
        MyString(const char* str);
      
    • 문제점
      • 송신 측 클래스의 private멤버를 액세스해야 변환이 가능한 경우
    • 변환 대상 송신 측 클래스의 private멤버를 액세스할 수 있는 멤버 함수가 송신 측 클래스에 정의되어 있어야 함
    • Meter 클래스와 Feet 클래스

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
        class Meter {
          int m;
          int cm;
        public:
          int getM() const { 
            return m; 
          }
          int getCM() const { 
            seturn cm; 
          }
        };
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        class Feet {
          int ft;
          int in;
        public:
          Feet(const Meter& m) {
            int cmeter = m.getM()*100 + m.getCM();
            in = static_cast<int>(cmeter/2.54+0.5);
            ft = in / 12;
            in %= 12;
          }
              
        };
      

생성자를 이용한 묵시적 형 변환의 금지

  • explicit으로 선언된 생성자

    1
    2
    3
    
      class MyString {
        explicit MyString(const char* str); // 생성자
      };
    
    • 묵시적 변환 금지
  • 에러 발생

    1
    2
    
      MyString str;
      str = "Programming"; // 자동 변환 안됨
    
  • 명시적 변환 시켜 사용

    1
    
      str = MyString{ "Programming" };
    
    1
    
      str = static_cast<MyString>("Programming");
    



연습 문제


  1. int형 값을 저장하는 배열을 표현하는 클래스에서 배열 멤버의 원소를 액세스하기 위한  []연산자의 원형을 올바르게 작성한 것은?

    a. int& operator [ ] (int i);

    • 값을 읽거나 값을 저장할 수 있어야 하므로 참조형을 사용할 필요가 있음
    • 원소를 참조하기 위한 첨자는 int형 값으로 해야 하며, 2항 연산자로서 배열 객체와 첨자를 각각 좌측과 우측 피 연산자로 간주하여 연산자의 매개변수로 int형 첨자를 받을 수 있게 선언함
  2. 위 지문은 두 객체의 내용을 서로 교환하기 위한 함수를 작성한 것이다. ㈀에 넣을 적절한 내용은?

    1
    2
    3
    4
    5
    
     void swap(C1& a, C2& b) {
       C1 tmp = // ___㈀___(a); // C1의 이동 생성자
       a = // ___㈀___(b); // C1의 이동 대입 연산자 사용
       b = // ___㈀___(tmp); // C1의 이동 대입 연산자 사용
     }
    

    a. std::move

    • std::move함수는 인수로 전달되는 객체의 rvalue 참조를 반환함으로써 이 함수에서 이동 생성자 및 이동 대입 연산자가 사용될 수 있게 함
  3. int형 값을 저장하는 배열을 표현하는 클래스에서 배열 멤버의 원소를 액세스하기 위한 []연산자의 원형을 올바르게 작성한 것은?

    1
    2
    3
    4
    5
    6
    7
    8
    
     class MyString {
       int len, bufSize;
       char* buf;
     public:
        
       bool operator >= (const MyString& mstr) const
         { return // ___㈀___; }
     };
    

    a. strcmp(buf, mstr.buf) >= 0

    • strcmp(str1, str2)는 str1과 str2가 같으면 0, str1이 str2보다 사전 순서로 앞서면 음, 그렇지 않으면 양의 값을 반환함
  4. 위 지문의 클래스에서 Pencils 객체를 int형인 연필 자루 수로 형 변환하는 연산자를 선언하기 위해 ㈀에 넣을 내용은?

    1
    2
    3
    4
    5
    6
    7
    8
    
     class Pencils {
       int dozen;         // 타
       int np;              // 낱개
        
     public:
       // ___㈀___         
         { return dozen * 12 + np; }
     };
    

    a. operator int( ) const

    • 변환하고자 하는 자료형을 연산자로 선언하면 형 변환 연산자가 만들어짐



정리 하기


  • 대입 연산자는 우측 피 연산자의 내용을 좌측 피 연산자에 복사하고, 이동 대입 연산자는 rvalue인 우측 피 연산자를 이동하는 연산자
  • std::move함수는 인수로 전달되는 객체의 rvalue 참조를 반환
  • 첨자 연산자([])는 첨자에 의해 지정되는 객체에 값을 저장하는 용도와 읽기 전용의 용도를 모두 고려하여 정의함
  • string은 문자열을 저장하기 위한 표준 C++ 라이브러리의 클래스로서, 문자열을 저장하고 처리하기 위한 유용한 기능을 제공함
  • 형 변환 연산자는 값을 제공하는 클래스에서 값을 받는 수신 측 클래스의 이름으로 연산자를 제공하거나, 값을 제공 받는 클래스에서 값을 제공하는 클래스의 객체를 인수로 받는 1인수 생성자를 정의하여 만듬

[C++ 프로그래밍] 8강 - 연산자 다중 정의

[C++ 프로그래밍] 10강 - 상속