프로그래밍의 규칙
공짜는 없다 !!
모든건 코드가 만들어져있기 때문에 가능한 것.
int main()
{
int Number = 10;
}
이게 가능한 이유는 뭘까?
int Number = int(10);
이것과 같은거다. int() 라는 생성자를 가지고 있는것이다.
class Myint
{
private:
int Value;
public:
Myint() : Value(0)
{
}
};
int main()
{
Myint MyNumber = 10;
}
나의int 클래스를 만들고 위의 int처럼 Myint MyNumber = 10 을 해주면
에러가 난다. 왜 int는 되고 내가 만든 int는 안되는 걸까?
int는 C++위원회에서 미리 만들어 놓은 자료형이다.
int가 정수를 받을수 있는건 C++위원회에서
그렇게 만들어 놨기 때문이다.
그럼 반대로 내가만든 Myint가 안되는 이유는?
정수를 받을수 있는 코드를 안만들어놨기 때문이고
정수를 받을수 있게 코드를 만들면 똑같이 가능하다.
특별한 건 없다 ! 생략되 있을 뿐이다.
class int
{
public:
int(int _Value)
{
}
};
만약에 int class가 위의 코드처럼 있다고 가정하면 저런 생성자가 있다는 거고,
우리가 내부를 건들 수 없을뿐 C++ 기본규칙에서 어긋나지 않는다.
Myint(int _Value) : Value(_Value)
내가 만든 Myint도 생성자에서 위의 코드처럼 만들어주면 사용이 가능해진다.
int Number = int(10);
Myint MyNumber = Myint(10);
똑같다.
int Number = int(10);
Number = 10;
Myint MyNumber = Myint(10);
MyNumber = 20;
위의 코드도 문제없이 실행된다.
단순히 생성자만 만들어 놓은게 전부인데 대입이 가능해진다.
(내가 만들어 놓은 기능이 아닌데 된다.) 이유는 뭘까?
생략 되어 있다. 컴파일러가 알아서 해주는거지 절대 공짜가 아니라는 거다.
만들어주는 이유는? 워낙 많이 사용하는 기능이기 때문이다.
public:
Myint& operator=(Myint& _Other)
{
this->Value = _Other.Value;
}
내가 만들어주지 않아도 위와 같은 코드가 생략되 있는거고
그렇기 때문에 에러 없이 코드를 사용할 수 있는거다.
Number = Number + Number; //사용 가능
MyNumber = MyNumber + MyNumber; //에러
왜 int로 만든 Number는 되고 Myint로 만든 MyNumber는 안되는걸까?
이유는 같다.int를 사용한 변수를 + 하는 기능을 컴파일러가 만들어 준것이다.
public:
Myint operator+(Myint& _Other) //MyNumber + MyNumber 사용 가능
{
return this->Value + _Other.Value;
}
Myint& operator+=(Myint& _Other)
{
this->Value += _Other.Value;
return *this
}
위의 코드에서 +에서는 Myint를 리턴하고
+=에서는 왜 Myint&를 리턴해줄까?
+연사자는 두 객체를 연산하여 하나의 임시객체 결과값을 리턴해준다.
즉 두개의 인자를 받고 하나의 임시객체를 리턴한다. 단순히 값만 리턴해주면 된다.
+=에서 자료형& 리턴하는 이유는?
this->Value = this->Value + _Other.Value 이렇게 동작한다.
+연산후 임시객체의 결과값을 리턴하지 않고 그 결과값을
자기 자신인 좌항 객체에 대입하여 변경하고 자기자신을 리턴한다.
결론은 값이 바뀐 자신의 레퍼런스를 반환해 줘야 한다.
public:
MyInt operator+(const MyInt& _Other)
{
return MyInt(this->Value + _Other.Value);
{
+연산에서 연산할 값으로 들어오는 _Other의 값은
일반적으로 값이 들어온 후 변경되지 않는다고 생각하기 때문에 const
리턴값에서 MyInt 이것도 생략되있는 거다.정확한 코드는 위와같은 코드이다.
int main()
{
MyInt Value = 10;
MyInt Left = 10;
MyInt Right = 10;
Value = Left + Right;
Value += Right = 20;
}
Value = Left + Right; 의 동작 방식은
Value = Left.operator+(Right); 함수 호출이랑 같은 방식이다.
아래의 Value += Right = 20 의 동작은
Value += Right.operator=(20) 이 되고
Value.operator+=(Right.operator=(20)) 이렇게 된다.
int main()
{
int Value = 10;
int Left = 10;
int Right = 10;
Right += 10 = 20; //에러
Right += Left = 20;
}
10은 상수에 20을 대입시키려고 하기때문에 에러가 난다.
만약 const int Left라고 만들면 똑같은 이유로 에러
(함수의 형태를 정확히 알자 !!)
public:
MyInt& operator++()
{
this->Value += 1;
return *this;
}
int main()
{
MyInt Value = 10;
++Value;
Value++;
}
증감 연산자를 만들고 사용하면 전위 증가 연산은 잘 되지만
후위 증가 연산은 사용이 안된다.그래서 특수한 문법을 만들어놨다.
MyInt operator++(int)
{
MyInt Return = this->Value;
this->Value += 1;
return Return;
}
후위와 전위를 구분하기 위해서 특별히 문법적으로 따로 정의해 놓은것이다.
기억해야할 점!!
위의 코드는 operator의 기능을 알아본거지 int와 똑같은 기능을 하는 MyInt를
하나 더 만든것은 아니다.operator+에서 안에 들어온 값이 바뀌어서
연산이 되든 -를 하든 틀렸다는 아닌것이다. 다만 가독성이 떨어진다.
연산자 오버로딩은 일반적인 사용자 정의 자료형에서는 잘 사용되지 않는다.
이유는 생각해보면 간단하다.내가 만약 Player 라는 클래스를 만들고
연산자 오버로딩으로 + 기능을 만들었다고 가정하면
int main()
{
Player Player1;
Player Player2;
Player1 + Player2;
}
이런 코드가 가능해진다.여기서 보면 Player끼리 더하는 코드가
어떤 결과값을 주며 무슨 기능을 하는건지 예상할 수 있을까?
알수없다.즉, 코드의 가독성이 떨어진다.
그렇기 때문에 보통 수학관련 개념을 class로 만들었을때 이용한다.
'C++' 카테고리의 다른 글
cout,GlobalClass (0) | 2020.12.16 |
---|---|
namespace (0) | 2020.12.16 |
UserTypeHeap (0) | 2020.12.15 |
Destructor(소멸자) (0) | 2020.12.13 |
DefaultParameter(기본인자) (0) | 2020.12.13 |