#include <iostream>
class Point2D
{
private:
	int mX;
	int mY;
public:
	Point2D():Point2D(0, 0) {}
	Point2D(int x, int y):mX(x), mY(y)
	{
	}
	void Print()
	{
		std::cout << "(" << mX << "," << mY << ")" << std::endl;
	}
	Point2D& operator++()
	{
		//멤버는 THIS로 자동으로 넘어옴
		++mY;
		++mX;
		return *this;
	}
	Point2D operator++(int x)
	{
		Point2D temp(mX, mY);
		//이미 위에서 만들어놓은 버전이 잇음
		++(*this); //this는 포인터라서 역참조후 증가시킴
		return temp;
	}
};
int main()
{
	Point2D pt1 {2,3}, pt2 {3,4};
	++pt1;
	// ++(Point2D(3, 4)); => ++1이랑 같은 것 (아무의미없음)
	pt2 = ++pt1;	//	34 34
	pt2 = pt1++;	//	34 23
	pt1.Print();
	pt2.Print();
}
#include <iostream>
class Point2D
{
private:
	int mX;
	int mY;
public:
	Point2D():Point2D(0, 0) {}
	Point2D(int x, int y):mX(x), mY(y)
	{
	}
	void Print()
	{
		std::cout << "(" << mX << "," << mY << ")" << std::endl;
	}
	int& operator[](int index)
	{
		if ( index == 0 )
		{
			return mX;
		}
		else if ( index == 1 )
		{
			return mY;
		}
		else
		{
			std::cerr << "invalid index!" << std::endl;
		}
		return mY;
		//참조형으로 바뀌어서 리턴값이 리터럴이면안됨
	}
}
};
class MyArray
{
public:
	MyArray(): mArray{}
	{
	}
	//인티젙아입의 대입을 하고싶을 떄
	int &operator[](int index)
	{
		return mArray[index];
	}
private:
	int mArray[10];
};
int main()
{
	Point2D pt1 {2,3}, pt2 {3,4};
	pt1[0] = 0;
	std::cout << pt1[0] << "," << pt1[1] << std::endl;
	//객체에 원하는 기능을 기존의 연산자로 쓸 수 있음
	//대입은 불가능함
	//pt1[0] = 0; 왼쪽 피 연산자가 int(rvalue의 값을 넣었기 때문)
	//x[1] = 0; 값을 저장한 l value여야함 => 참조형이 필요해짐
	MyArray array;
	array[0] = 1;
	std::cout << array[0] << std::endl;
}
class Point2D
{
private:
	int mX;
	int mY;
public:
	Point2D():Point2D(0, 0) {}
	Point2D(int x, int y):mX(x), mY(y)
	{
	}
	void Print()
	{
		std::cout << "(" << mX << "," << mY << ")" << std::endl;
	}
    
	//암시적 형변환 연산자
	//내부가 변경할 필요 없으니 const
	//추측가능하기 때문에 반환 타입은 없음
	operator float()const //강제로 float안쓰도록 문법이 변함
	{
		return sqrt(mX * mX + mY * mY);
	}
};
int main()
{
float dist = pt1;
	std::cout << dist << std::endl;
	std::cout << (float) pt1 << std::endl;
}   
+functor(함수 객체)
class Point2D
{
private:
	int mX;
	int mY;
public:
	Point2D():Point2D(0, 0) {}
	Point2D(int x, int y):mX(x), mY(y)
	{
	}
	void Print()
	{
		std::cout << "(" << mX << "," << mY << ")" << std::endl;
	}
	
	//함수 호출 연산자 ( )
	//함수 객체(functor
	void operator () ()// 앞은 연산자 기호 뒤는 매개변수
	{
		mX = 0;
		mY = 0;
	}
	void operator () (int x, int y)
	{
		mY = y;
		mX = x;
	}
};
int main()
{	
	
	pt1(); //인스턴스에 ()
	//생성자와 다름
	pt1.Print(); //초기화가 0으로 되어있을 것
	pt1(2, 3);
	pt1.Print();
}
#include<iostream>
class Point2D
{
private:
	int mX;
	int mY;
public:
	Point2D():Point2D(0, 0) {}
	Point2D(int x, int y):mX(x), mY(y)
	{
	}
	friend std::ostream &operator<<(std::ostream &os,const Point2D& pt);
};
//정해저 있음
std::ostream &operator<<(std::ostream &os, const Point2D &pt)
{
	os << "(" << pt.mX << "," << pt.mY << ")";
	return os;
}
//이 연산자는 friend가 아니면 불가능 왜?
//이 클래스는 제공되는 클래스임(코드가 숨겨져있음)=>못 건들임
//그래서 멤버함수로 넣을 수 없음
//전역함수 말고 생성할 수 없음
int main()
{
	Point2D pt1 {2,3}, pt2 {3,4};
	std::cout << pt1 << std::endl;
}
몇가지 연산자들은 오버로딩을 하지 않음 ex. { }
std::ostream &operator<<(std::ostream &os, const Point2D &pt)
cout<<x<<y<<z;
cout<<y<<;
cout<<z;
+연속된 점 표기법 => UI
c1. function()
.function1()
.function2()
.function3()