산술 연산자 오버로딩 하기
- int나 double같은 기본적인 자료형들은 자기들 사이의 산술연산자들이 모두 정의가 되어있어서 편하게 코딩할 수 있다
- 사용자 정의 자료형 끼리도 산술 연산자를 정의할 수 있다.
- 연산자의 우선순위는 항상 그대로다.
(내가 만든 곱하기 연산자는 내가만든 더하기 연산자보다 항상 우선)
예제
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int& getCents() { return m_cents; }
// friend로 사용해도 되고, 멤버 직접받기도 가능하다
// 멤버 직접 사용을 위해 파라미터를 하나 줄이고 this를 사용한다.
Cents operator + (const Cents& c2)
{
return Cents(this->m_cents + c2.getCents());
}
};
int main()
{
Cents cents1(6);
Cents cents2(8);
cout << (cents1 + cents2 + Cents(6) + Cents(10)).getCents() << endl;
return 0;
}
입출력 연산자 오버로딩 하기
사용 예제
#include <iostream>
#include <fstream>
using namespace std;
class Point
{
private:
double m_x, m_y, m_z;
public:
Point(double x = 0.0, double y = 0.0, double z = 0.0)
: m_x(x), m_y(y), m_z(z)
{}
double getX() { return m_x; }
double getY() { return m_y; }
double getz() { return m_z; }
friend std::ostream& operator << (std::ostream &out, const Point &point)
{
out << "( " << point.m_x << " " << point.m_y << " " << point.m_z << " )";
return out;
}
friend std::istream& operator >> (std::istream &in, Point &point)
{
in >> point.m_x >> point.m_y >> point.m_z;
return in;
}
};
int main()
{
ofstream of("/Users/hyengchan/Documents/dev/cpp_self_study/Chapter9/Chap9_2_io_operator_overloading/out.txt");
Point p1(0.0, 1.2, 6.2), p2(3.5, 12.2, 6.9);
cout << p1 << " " << p2;
of << p1 << " " << p2 << endl;
of.close();
Point p3, p4;
cin >> p3 >> p4;
cout << p3 << " " << p4;
return 0;
}
단항 연산자 오버로딩 하기
사용 예제
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int& getCents() { return m_cents; }
Cents operator - () const
{
return Cents(-m_cents);
}
bool operator ! () const
{
// 돈이 없을때만 true 출력하게 한다
return (m_cents == 0 ) ? true : false;
}
friend std::ostream& operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return out;
}
};
int main()
{
Cents cents1(6);
Cents cents2(0);
cout << cents1 << endl;
cout << -cents1 << endl;
cout << -Cents(-10) << endl;
cout << !cents1 << " " << !cents2 << endl;
return 0;
}
비교연산자 오버로딩 하기
==
오버로딩 예제
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int& getCents() { return m_cents; }
friend bool operator == (const Cents &c1, const Cents &c2)
{
return c1.m_cents == c2.m_cents;
}
friend std::ostream& operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return out;
}
};
int main()
{
Cents cents1(6);
Cents cents2(6);
if(cents1 == cents2)
cout << "Equal " <<endl;
return 0;
}
sorting(크기 비교) 예제
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
using namespace std;
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
int& getCents() { return m_cents; }
// sort 할때는 > 말고 < 로 만들어 줘야함.
// return 부등호를 >로 바꾸면 역순 정렬한다.
friend bool operator < (const Cents &c1, const Cents &c2)
{
return c1.m_cents < c2.m_cents;
}
friend std::ostream& operator << (std::ostream &out, const Cents ¢s)
{
out << cents.m_cents;
return out;
}
};
int main()
{
vector<Cents> arr(20);
for(unsigned int i = 0; i < 20; ++i)
arr[i].getCents() = i;
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(arr.begin(), arr.end(),g);
for(auto &e : arr)
cout << e << " ";
cout << endl;
// 크기 비교를 위해 비교 연산자를 만들어줘야함
std::sort(begin(arr), end(arr));
for (auto &e : arr)
cout << e << " ";
cout << endl;
return 0;
}
증감 연산자 오버로딩 하기
예제
class Digit
{
private:
int m_digit;
public:
Digit(int digit = 0) : m_digit(digit) {}
// 전위형
Digit & operator ++ ()
{
++m_digit;
// 자기 자신을 리턴한다.
return *this;
}
// 후위형은 parameter에 dummy형이 아무거나 들어가야함
Digit operator ++ (int)
{
Digit temp(m_digit);
++(*this);
return temp;
}
friend std::ostream& operator << (std::ostream &out, const Digit &d)
{
out << d.m_digit;
return out;
}
};
int main()
{
Digit d(5);
cout << ++d << endl;
cout << d << endl;
cout << d++ << endl;
cout << d << endl;
return 0;
}
첨자 연산자 오버로딩 하기
사용 예제
using namespace std;
class IntList
{
private:
int m_list[10];
public:
int & operator [] (const int index)
{
assert(index >= 0);
assert(index < 10);
return m_list[index];
}
};
int main()
{
IntList my_list;
my_list[3] = 10;
cout << my_list[3] << endl;
return 0;
}
괄호 연산자 오버로딩과 함수 객체
- 괄호 연산자는 특징상 함수를 호출할 때 사용하는 괄호랄 똑같다.
- 괄호 연산자를 오버로딩 하면 마치 함수가 객체인것 처럼(functor) 사용가능
사용 예제
class Accumulator
{
private:
int m_counter = 0;
public:
int operator()(int i) { return (m_counter += i ); }
};
int main() {
Accumulator acc;
cout << acc(10) << endl;
cout << acc(20) << endl;
return 0;
}
형변환(static_cast
)을 오버로딩 하기
예제
class Cents
{
private:
int m_cents;
public:
Cents(int cents = 0) { m_cents = cents; }
int getCents() const { return m_cents; }
void settCents(int cents) { m_cents = cents; }
// 형변환 오버로딩
operator int()
{
return m_cents;
}
};
class Dollar
{
private:
int m_dollars = 0;
public:
Dollar(const int& input) : m_dollars(input) {}
operator Cents()
{
return Cents(m_dollars * 100);
}
};
void printInt(const int &value)
{
cout << value << endl;
}
int main() {
Cents cents(7);
printInt(cents);
Dollar dol(2);
Cents cents2 = dol;
printInt(cents2);
return 0;
}
대입 연산자 오버로딩, 깊은 복사, 얕은 복사
- 동적 할당된 메모리에 대한 포인터 변수를 멤버로써 가지고 있는 클래스의 경우 복사를 하거나 대입을 할 때 깊은 복사냐 얕은 복사냐 하는 문제로 인해서 대입연산자 오버로딩 혹은 복사 생성자 구현이 좀 까다로워 진다.
예제는 github 9_11 확인
이니셜 라이저 리스트 { }
- 클래스같은 사용자 정의 자료형에서 생성자나 대입연산자를 만들때 편하게 사용할 수 있다.
예제는 github 9_12 확인
잘 정리해두셨군요^^
좋은 글 잘 봤습니다.