둠치킨
코딩하는 둠치킨
둠치킨

블로그 메뉴

  • 홈
  • 분류 전체보기 (218)
    • BOJ (171)
      • 스택 (14)
      • 큐 (5)
      • 덱 (4)
      • 그래프 (30)
      • 배열 (8)
      • 재귀 (12)
      • 브루트 포스 (2)
      • 그리디 알고리즘 (7)
      • 다이내믹 프로그래밍 (13)
      • 백트래킹 (24)
      • 기하학 (4)
      • 트리 (4)
      • 구현 (14)
      • 수학 (3)
      • 맵 (1)
      • 다익스트라 (2)
      • 누적합 (5)
    • 자료구조 (14)
      • 스택 (3)
      • 큐 (5)
      • 덱 (2)
      • 그래프 (1)
      • 트리 (1)
      • 힙 (1)
      • 정렬 (1)
    • C++ (11)
      • 모두의코드 (2)
      • Effective C++ (3)
      • C++ STL (6)
    • 컴파일러 (1)
    • OS (17)
    • 컴퓨터 구조 (2)
    • Unreal Engine 5 (2)

공지사항

전체 방문자
오늘
어제

인기 글

최근 글

태그

  • BFS
  • boj
  • Bruteforce
  • C
  • C++
  • C++ STL
  • Cache Memory
  • deadlock
  • DFS
  • Effective C++
  • java
  • Mutex
  • next_permutation
  • os
  • Process
  • rotate
  • semaphore
  • spin lock
  • STL
  • STL C++
hELLO · Designed By 정상우.
둠치킨

코딩하는 둠치킨

C++/C++ STL

C++ STL (뇌를 자극하는) - 1장. 연산자 오버로딩 (Section 6~7)

2025. 7. 23. 20:09

※ 제가 개인적으로 공부하는 것이라 요약하거나 책에서 빠진 내용이 있을 수 있습니다 ※

Section 6. STL에 필요한 주요 연산자 오버로딩

함수 호출 연산자 오버로딩은 객체를 함수처럼 동작하게 하는 연산자입니다. C++에서 Print(10)이라는 함수 호출 문장은 다음 세 가지로 해석할 수 있습니다.

1. 함수 호출 : Print가 함수 이름

2. 함수 포인터 : Print가 함수 포인터

3. 함수 객체 : Print가 함수 객체

struct FuncObject
{
public:
	void operator() (int arg) const
    {
    	cout << "정수: " << arg << endl;
    }
};

void Print1(int arg)
{
	cout << "정수 : " << arg << endl;
}

int main()
{
	void (*Print2)(int) = Print1;
    FuncObject Print3;
    
    Print1(10); // 1. 함수를 이용한 출력
    Print2(10); // 2. 함수 포인터 이용 출력
    Print3(10); // 3. 함수 객체를 사용한 정수 출력 (Print3.operator(10))
}

 

예제 1-17 정수를 저장하는 간단한 Array 클래스

class Array
{
	int *arr;
    int size;
    int capacity;
    
public:
	Array(int cap=100) : arr(0), size(0), capacity(cap)
    {
    	arr = new int[capacity];
    }
   	
    ~Array()
    {
    	delete [] arr;
    }
    
    void Add(int data)
    {
    	if(size < capacity)
        	arr[size++] = data;
    }
    
    int Size() const
    {
    	return size;
    }
    
    int operator[] (int idx) const
    {
    	return arr[idx];
    }
};

int main()
{
	Array ar(10);
    ar.Add(10);
    ar.Add(20);
    ar.Add(30);
    
    for(int i=0; i<ar.Size(); i++)
    	cout << ar[i] << endl; // ar.operator[] (i)와 같다
    
    return 0;
}

 

[] 연산자 오버로딩은 ar[i] = 10과 같은 쓰기 연산도 가능해야 하므로 operator[]() 함수는 const함수와 비 const 함수 모두를 제공해야 한다.

...
    int operator[] (int idx) const
    {
    	return arr[idx];
    }
    
    int& operator[](int idx)
    {
    	return arr[idx];
    }
 };

 

메모리 접근, 클래스 멤버 접근 연산자 오버로딩 (*, -> 연산자)

*, -> 연산자는 스마트 포인터나 반복자 (iterator) 등의 특수한 객체에 사용.

PointPtr 클래스의 소멸자를 이용해 동적으로 할당된 Point 객체(heap 객체)를 자동으로 제거

class Point
{
    int x;
    int y;
public:
    Point(int _x = 0, int _y = 0) : x(_x), y(_y) { }
    void Print() const {cout << x << ',' << y << endl; }
};

class PointPtr
{
    Point* ptr;
public:
    PointPtr(Point *p) : ptr(p) { }
    ~PointPtr()
    {
    	delete ptr;
    }
    
    Point* operator->() const
    {
    	return ptr;
    }
    
    Point& operator*() const
    {
    	return *ptr;
    }
};

int main()
{
    Point* p1 = new Point(2, 3);    // 일반 포인터
    PointPtr p2 = new Point(5, 5);  // 스마트 포인터
    
    p1->Print(); // p1->Print() 호출
    p2->Print(); // p2.operator->()->Print() 호출
    
    (*p1).Print(); // (*p1).Print() 호출
    (*p2).Print(); // p2.operator*().Print() 호출
    
    delete p1;
    // p2의 소멸자에서 자동 해제
    
    return 0;
}

 

Section 7. 타입 변환 연산자 오버로딩

타입 변환은 두 가지

1. 생성자를 이용한 타입 변환

2. 타입 변환 연산자 오버로딩을 이용한 타입 변환

 

생성자를 이용한 타입 변환

Point 객체에 정수 대입? 가능 -> 생성자를 이용한 타입 변환 중 암시적 생성자 호출

Point pt;
pt = 10; // Point(10, 0) 암시적 생성자 호출

 

이렇게 실수로 정수를 대입해도 컴파일이 성공해서 의도치 않은 버그로 연결될 수 있어서 의도하지 않는다면 생성자는 명시적 호출만 가능하도록 explicit 키워드를 지정.

...
explicit Point(int _x =0, int _y = 0) : x(_x), y(_y) { }
...
};

int main()
{
    Point pt;
    // pt = 10; -> 오류, 암시적 생성자 호출 불가능
    pt = Point(10); // 명시적 생성자 호출만 가능
}

 

타입 변환 연산자 오버로딩을 이용한 타입 변환

예시 : Point 클래스의 int 타입 변환 연산자

class Point
{
    int x;
    int y;
    ...
    
    operator int() const
    {
    	return x;
    }
};

int main()
{
    int n = 10;
    
    Point pt(2, 3);
    n = pt;
    cout << n << endl; // 2 출력
}

 

1장 연습문제

1.4 다음이 컴파일될 수 있게 최소한의 String 클래스를 작성하세요.

// Q.
String s("Hello!");
const char* sz = s;

// A.
#include <iostream>
#include <cstring>
using namespace std;

class String
{
    char buf[100];
public:
    String(const char* sz)
    {
    	strcpy(buf, sz);
    }
    
    // 핵심은 여기 -> String 타입을 const char* 타입 변환을 위해
    // operator const char* () const 구현
    operator const char* () const
    {
    	return buf;
    }
};

int main()
{
	...
}

 

1.5 다음이 컴파일될 수 있게 최소한의 String 클래스를 작성하세요.

// Q.
const char* sz = "Hello!";
String s("Hi~!");
s = sz;

// A.
// 방법 1
// String 클래스의 = 연산은 얕은 복사(shallow copy)로 암묵적인 생성자를 이용한 방법
#include <iostream>
#include <cstring>
using namespace std;

class String
{
    char buf[100];
public:
    String(const char* sz)
    {
    	strcpy(buf, sz);
    }
};

// A
// 방법 2
// 깊은 복사
#include <iostream>
#include <cstring>
using namespace std;

class String
{
    char buf[100];
public:
    String(const char* sz)
    {
    	buf = new char[strlen(sz) + 1];
    }
    ~String()
    {
    	delete [] buf;
    }
    const String& operator=(const String& arg)
    {
    	delete[] buf;
        buf = new char[strlen(arg.buf) + 1];
        strcpy(buf, arg.buf);
        
        return *this;
    }
};
저작자표시 (새창열림)

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

C++ STL (뇌를 자극하는) - 4장. 함수 템플릿 (Section 2 ~ 3)  (0) 2025.07.28
C++ STL (뇌를 자극하는) - 4장. 함수 템플릿 (Section 1)  (2) 2025.07.27
C++ STL (뇌를 자극하는) - 3장. 함수 객체란  (1) 2025.07.25
C++ STL (뇌를 자극하는) - 2장. 함수 포인터  (2) 2025.07.24
C++ STL (뇌를 자극하는) - 1장. 연산자 오버로딩  (0) 2025.07.08
    'C++/C++ STL' 카테고리의 다른 글
    • C++ STL (뇌를 자극하는) - 4장. 함수 템플릿 (Section 1)
    • C++ STL (뇌를 자극하는) - 3장. 함수 객체란
    • C++ STL (뇌를 자극하는) - 2장. 함수 포인터
    • C++ STL (뇌를 자극하는) - 1장. 연산자 오버로딩
    둠치킨
    둠치킨
    코딩 공부를 위한 코딩 블로그 기록 일기

    티스토리툴바