연산자 오버로딩
: c++에서 제공하는 기본 타입이 아닌
: 클래스, 사용자 정의 타입에도 연산자를 사용할 수 있게 하는 문법
>>연산자 오버로딩의 핵심
: 클래스 타입(사용자 정의 타입)의 객체에 연산자 사용
== > 컴파일러가 정의된 함수를 호출
ex)
식 : p1+p2
해석 : p1.operator+(p2)
ex) 연산자 오버로딩 operator+()의 예시
#include <iostream>
using namespace std;
class Point
{
private:
int x;
int y;
public:
//생성자
Point(int _x=0, int _y=0): x(_x), y(_y){}
void Print() const
{
cout << x << ", " << y << endl;
}
const Point operator+(const Point& arg)
{
Point pt;
pt.x = this->x + arg.x;
pt.y = this->y + arg.y;
return pt;
}
};
int main(void)
{
Point p1(2, 3), p2(5, 5);
Point p3;
p3 = p1 + p2;
p3.Print();
p3 = p1.operator+(p2);
p3.Print();
return 0;
}
#const멤버 함수와 비 const멤버 함수
- const 멤버함수 : 객체 내의 멤버 변수를 변경하지 않음을 보장
=> const 객체는 const 멤버 함수만 호출 가능
#단항 연산자 오버로딩
전위 연산 : operator++()
후위 연산 : operator++(int)
//전위 연산자 오버로딩
const Point& operator++()
{
++x;
++y;
return *this;
}
//후위 연산자 오버로딩
const Point operator++(int)
{
Point pt(x, y);
x++;
y++;
return pt;
}
};
#전역함수를 이용한 연산자 오버로딩
>> 연산자 오버로딩의 방법 2가지
1) 멤버 함수를 이용한 오버로딩
2) 전역함수를 이용한 오버로딩
=> 멤버함수를 이용한 오버로딩을 사용하지 못하는 경우가 생김
ex)
상수+객체
=> 상수.operator+(객체)로 해석되지 못함
>>방법에 따른 해석 2가지
ex) p1==p2
1. 멤버 함수 : p1.operator==(p2)
2. 전역 함수 : operator==(p1, p2)
#전역함수 연산자 오버로딩
#include <iostream>
using namespace std;
class Point
{
private:
int x;
int y;
public:
Point(int _x = 0, int _y = 0) :x(_x), y(_y) {};
void Print() const
{
cout << x << ", " << y << endl;
}
int GetX() const { return x; }
int GetY() const { return y; }
friend const Point& operator-(const Point& p1, const Point& p2);
};
const Point& operator-(const Point& p1, const Point& p2)
{
return Point(p1.GetX() - p2.GetX(), p1.GetY() - p2.GetY());
}
=> 전역 함수는 private 멤버에 접근 불가
=> 극복방법1. getX, getY 등 getter함수를 이용
=> 극복방법2. friend 선언(모든 클래스 멤버에 접근 가능)
#STL에 필요한 주요 연산자 오버로딩
>>함수 호출 연산자 오버로딩 : operator()
: 객체를 함수처럼 동작하게 하는 연산자
ex)
#include <iostream>
using namespace std;
struct FuncObject
{
public:
void operator()(int a )
{
cout << "정수 : " << a << endl;
}
void operator()(int a ,int b)
{
cout << "정수 : " << a <<", "<< b << endl;
}
void operator()(int a, int b, int c)
{
cout << "정수 : " << a <<", " << b << ", " << c << endl;
}
};
#키워드 : struct vs class
struct : default가 public
class : default가 private
>>배열 인덱스 연산자 오버로딩 : operator[]
:많은 객체를 저장하고 관리하는 객체(컨테이너 객체)에 사용
ex)
- array에서 const 함수 구분이 필요한 이유
int operator[] (int idx) -> 쓰기/읽기
int& operator[] (int idx) const -> const객체가 읽기만 가능
#include <iostream>
using namespace std;
class Array
{
private:
int* arr;
int size;
int capacity;
public:
Array(int cap) : 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;
}
//const 함수
//그저 읽기 위한 것
int operator[](int idx) const
{
return arr[idx];
}
//비 const 함수
//쓰기용 함수 ->주소값 넘겨줌
int& operator[](int idx)
{
return arr[idx];
}
};
#메모리 접근, 클래스 멤버 접근 연산자 오버로딩
- operator -> : 포인터 클래스가 일반멤버에 접근하기 위해서
- operator * : 포인터가 가리키는 객체 반환
-> 스마트 포인터나 반복자에 사용
ex1) 스마트 포인터 예제 : 객체 소멸시 자동으로 메모리 반환(소멸자 활용)
#include <iostream>
using namespace std;
class Point
{
private:
int x;
int y;
public:
Point(int _x, int _y) : x(_x), y(_y) {};
void Print()
{
cout << x << ", " << y << endl;
}
};
class Pointptr
{
private:
Point* ptr;
public:
Pointptr(Point* p) : ptr(p) { };
Point& operator*()
{
return *ptr;
}
Point* operator->()
{
return ptr;
}
//자동 메모리 반환
~Pointptr()
{
delete ptr;
}
};
int main6(void)
{
Point* p1 = new Point(2, 3);
Pointptr p2 = new Point(5, 5);
p1->Print();
p2->Print();
cout << endl;
(*p1).Print();
(*p2).Print();
cout << endl;
delete p1;
return 0;
}
#타입 변환 연산자 오버로딩
1) 생성자를 이용한 타입변환
2) 타입변환 연산자 오버로딩을 이용한 타입 변환 => 반환타입 미지정 like 생성자, 소멸자
ex) operator int () const ->int로 변환되어야 하는 상황
ex) operator double () const -> double로 변환되어야 하는 상황
ex1) 생성자를 이용한 타입변환
=>임시 객체가 형성되어 복사됨
class B
{
public :
B() { cout << "B() 생성자 호출" << endl; }
B(A& _a) { cout << "B(A &_a) 생성자 호출" << endl; }
B(int n) { cout << "B(int n) 생성자 호출" << endl; }
B(double d) { cout << "B(double d) 생성자 호출" << endl; }
};
=>만약 생성자를 이용한 형변환을 의도하지 않는다면?
=> explicit키워드 = 명시적 호출만 가능
#include <iostream>
using namespace std;
class Point
{
private:
int x;
int y;
public:
explicit Point(int _x, int _y) : x(_x), y(_y){};
void Print() const { cout<< x << ", " << y << endl;}
}
=> Point p1= Point(10) // 이건 가능
=> Point p1= 10 //이건 explicit 때문에 불가능
ex2) 타입변환 연산자를 이용한 변환
#include <iostream>
using namespace std;
class A
{};
class B
{
int x;
public:
B() { cout << "B() 생성자 호출" << endl; }
B(A& _a) { cout << "B(A &_a) 생성자 호출" << endl; }
B(int n): x(n) { cout << "B(int n) 생성자 호출" << endl; }
B(double d) { cout << "B(double d) 생성자 호출" << endl; }
//타입 변환 연산자
operator int() const
{
return 3;
}
operator A() const
{
cout << "operator A() 호출" << endl;
return A();//임시 객체 반환
}
operator double() const
{
cout << "operator double()호출" << endl;
return 5.5;
}
};
int main(void)
{
A a;
int n = 10;
double d = 5.5;
B b;
b = a; // B(A a)가 형성 후 복사생성자 호출
b = n; // B(int n) 가 형성 후 복사생성자 호출
b = d; // B(double d)가 형성 후 복사성자 호출
a = b; // b.operator A()
n = b; // b.operator int()
d = b; // b.operator double()
cout << n << endl;
cout << d << endl;
return 0;
}
=>결과
'C언어 기초' 카테고리의 다른 글
[CPP] strcpy_s - L buffer is too small (0) | 2023.08.04 |
---|---|
[열혈 C] 도전 프로그래밍2 문제풀이 (0) | 2023.02.08 |
[C언어] switch - goto문 (0) | 2023.02.02 |
chapter 4 : 데이터 표현방식의 이해 (0) | 2022.11.13 |
chapter 3. 변수, 연산자, scanf 함수 (0) | 2022.11.11 |