티스토리 뷰

추가되는 기능

    • C++ class/struct에서는 멤버 변수를 선언과 함께 초기화할 수 있다.

      class Object {
          private:
          int value = 0;
      
          public:
          void print() {
              std::cout << value << std::endl;
          }
      };
      
      int main() {
          Object o;
          o.print();
      }
      
      0
    • C++ class/struct에서는 기본 연산자를 오버로딩할 수 있다.
    • class Object {
          private:
          int value = 0;
      
          public:
          Object operator+(int add) {
              value += add;
      
              return *this;
          }
      
          void print() {
              std::cout << value << std::endl;
          }
      };
      
      int main() {
          Object o1;
          Object o2 = o1 + 10;
          o2.print();
      }
      
      10
    • 객체 선언시 다른 객체를 대입할 때는 복사 생성자가 호출되고, 객체가 선언된 이후 다른 객체를 대입할 때는 대입 연산자가 호출된다.
      class Object {
          private:
          int value = 0;
      
          public:
          Object(const Object& o) {
              std::cout << "Object(const Object&) << std::endl;
              value = o.value;
          }
      
          Object& operator=(const Object& o) {
              std::cout << "operator=(const Object&)" << std::endl;
              value = o.value;
      
              return *this;
          }
      
          void print() {
              std::cout << value << std::endl;
          }
      };
      
      int main() {
          Object o1;
          Object o2 = o1;
          Object o3;
          o3 = o1;
      }
      
      Object(const Object&)
      operator=(const Object&)
    • Class 정의 내에 friend로 선언된 class는 private 멤버에 접근할 수 있다.
      class A {
          friend class B;
          
          private:
          int value = 10;
      };
      
      class B {
          public:
          int get_A_value(A a) {
              return a.value;
          }
      };
      
      int main() {
          A a;
          B b;
          std::cout << b.get_A_value(a) << std::endl;
          
          return 0;
      }
      10
      
    • 멤버 함수 정의시 friend 기호를 붙인다면 class 외부 전역 함수처럼 쓰인다. 이때, class의 private 멤버에는 접근할 수 있다.
      class A {
          private:
          int value = 10;
          
          public:
          friend int get_value(A a) {
              return a.value;
          }
      };
      
      class B {
          public:
          int get_A_value(A a) {
              return get_value(a);
          }
      };
      
      int main() {
          A a;
          B b;
          std::cout << b.get_A_value(a) << std::endl;
          
          return 0;
      }
      10
      

목표

    • vector class에 맞는 적절한 기본 연산자를 오버로딩한다.

디자인

    • 다음 연산자를 오버로딩한다.
      • vector& operator=(const vector& v)
        인수로 받는 vector의 멤버 변수를 적절히 복사한 다음 자기 자신의 참조를 반환한다.

      • vector& operator+=(int element)

      • friend std::ostream& operator<<(std::ostream& ostream, const vector& v)
        인수로 받는 std::ostream에 적절한 출력을 한 다음 std::ostream을 반환한다. 이때 chaining을 위해 참조를 반환한다. chaining은 다음의 꼴을 갖는다.
        std::cout << v1 << v2 << ... << std::endl;
        
        chaining을 사용하지 않을 때는 다음과 같이 구현해야한다.
        std::cout << v1;
        std::cout << v2;
        ...
        std::cout << endl;

      • int& operator[](int index)
        v[index] 꼴의 접근을 정의한다. 이때, v[index] = element; 꼴의 식을 사용할 수 있다.

      • int operator[](int index)
        v[index] 꼴의 접근을 정의한다. 이때, v[index] = element; 꼴의 식을 사용할 수 없다.
        class Object {
            private:
            int arr[10];
        
            public:
            int& operator[](int index) {
                std::cout << "mutable" << std::endl;
                return arr[index];
            }
        
            int operator[](int index) const {
                std::cout << "immutable" << std::endl;
                return arr[index];
            }
        };
        
        int main() {
            Object o1;
            const Object o2;
            o1[2] = 10; // OK
            o2[2] = 10; // Error
        }

구현

constexpr int INITIAL_SIZE = 10;

class vector {
    private:
    int* data;
    int capacity;
    int length;
    
    bool ensure_capacity(int to_add) const {
        return length + to_add < capacity;
    }
    
    void increase_capacity() {
        auto tmp = data;
        data = new int[capacity * 2];
        std::copy(tmp, tmp + length, data);
        delete[] tmp;
        capacity *= 2;
    }
    
    void shiftLeft(int offset, int width) {
        int tail_length = length - offset - width;
        int* tail = new int[tail_length];
        std::copy(data + offset + width, data + length, tail);
        std::copy(tail, tail + tail_length, data + offset);
        delete[] tail;
    }
    
    void shiftRight(int offset, int width) {
        int tail_length = length - offset;
        int* tail = new int[tail_length];
        std::copy(data + offset, data + length, tail);
        std::copy(tail, tail + tail_length, data + offset + width);
        delete[] tail;
    }
    
    public:
    vector() {
        data = new int[INITIAL_SIZE];
        capacity = INITIAL_SIZE;
        length = 0;
    }
    
    vector(const vector& v) {
        data = new int[v.capacity];
        capacity = v.capacity;
        length = v.length;
        std::copy(v.data, v.data + v.length, data);
    }
    
    ~vector() {
        delete[] data;
    }
    
    void add(int element) {
        if (!ensure_capacity(1))
            increase_capacity();
        
        *(data + length++) = element;
    }
    
    void add(int index, int element) {
        if (!ensure_capacity(1))
            increase_capacity();
        
        shiftRight(index, 1);
        *(data + index) = element;
        length++;
    }
    
    int get(int index) const {
        return *(data + index);
    }
    
    int set(int index, int element) {
        auto tmp = *(data + index);
        *(data + index) = element;
        return tmp;
    }
    
    int remove(int index) {
        auto tmp = *(data + index);
        shiftLeft(index, 1);
        length--;
        
        return tmp;
    }
    
    void print() const {
        std::cout << '{';
        for (int i = 0; i < length; i++)
            std::cout << *(data + i) << ((i < length - 1) ? ", " : "");
        std::cout << '}' << std::endl;
    }
    
    vector& operator=(const vector& v) {
        data = new int[v.capacity];
        capacity = v.capacity;
        length = v.length;
        std::copy(v.data, v.data + capacity, data);
        
        return *this;
    }
    
    vector& operator+=(int element) {
        add(element);
        
        return *this;
    }
    
    int& operator[](int index) {
        return *(data + index);
    }
    
    int operator[](int index) const {
        return *(data + index);
    }

    std::ostream& operator<<(std::ostream& ostream, const vector& v) {
        ostream << '{';
        for (int i = 0; i < length; i++)
            ostream << *(data + i) << ((i < length - 1) ? ", " : "");
        ostream << '}';
    }
};


'C++ > C to C++' 카테고리의 다른 글

[C to C++] 상속  (0) 2019.02.01
[C to C++] 템플릿  (0) 2019.02.01
[C to C++] friend, 연산자 오버로딩  (0) 2019.01.31
[C to C++] 함수 오버로딩  (0) 2019.01.31
[C to C++] 생성자, 소멸자, 복사 생성자  (0) 2019.01.29
[C to C++] 구조체를 클래스로 재정의하기  (0) 2019.01.29
댓글
댓글쓰기 폼