달력

10

« 2018/10 »

  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
  •  




시작은 단축 평가 처리에 대해서 언급되어 있다.

복합적인 불린 표현식을 평가 할 때.
모든 조건을 다 보는것이 아니라. 특정 조건으로 인해 최종 결과 값이, 참 또는 거짓 이라고 판명이 났을 때.
남은 조건들을 검사하지 않고 넘어 가는 것을 말하는데.


여기 까지는 이미 알고 있거나, "아 그렇군!" 하고 넘어 가면 그만인데
이제 &&, || 연산자를 오버로딩 한다고 생각하자.

다음과 같은 문제가 발생한다.

다음 처럼 보여진다는 것이다.
잘 이해가 가지 않을 수도 있지만.
쉽게 생각하면 문제는 다음과 같다.
첫째, 모두 검사를 해야 하기 때문에 단축 평가가 이루어 지지 않는다.
둘째, ex1이 먼저 평가 될지, ex2가 먼저 평가 될지 모른다는것이다.
단축 평가는 c, c++에서 정해져 있는 기본 기능이다.
만약 &&, || 연산자를 오버로딩 하지 않았다는 전재로.
단축 평가를 생각하면서 조건식을 넣었던 A씨는
B씨의 오버로딩으로 문제가 발생할 여지가 존재한다는 것이다.
물론 그런 부분을 처음에 약속하여 방지 하는 것은 가능할지도 모르겠으나.
그것이 옳지 않은 방법이라는 것은 구지 말하지 않아도 충분히 알 것이라고 생각한다.

다음은 ,(쉼표) 연산자 인데.
사실 흔히 사용하는 연산자는 아니다.
사용하는 좋은 예를 코드로 보여주고 있는데.
내용은 다음과 같다.

문자열을 반전시키는 함수인데,
마지막 부분을 보면 ++i, --j 를 볼 수 있다.
, 연산자의 경우 순서를 따지면
먼저 i를 증가 시키고,
그 다음 j를 증가 시킨다.
그 순서에 의문이 생긴다면,
처럼 해보자.
값은 --j가 나올 것이다.
여튼, 이것 또한 문제만 콕 찝어서 넘어 가자면,
오버로딩 하였을 때, 그 안에서 --j를 먼저 실행할지, ++i를 먼저 실행할지
순서를 보장 할 수 없다는것!!
그렇기 때문에 , 연산자 또한 오버로딩을 하지 말아라! 라는것이 이번 항목의 결론인것 같다.

한가지 의문은 오버로딩을 할 순있지만, 해서 좋지 않을 것이라면,
애초에 하지 못하게 하는것이 더 낫지 않았을까? 하는 생각도 들긴 한다만...

뭐... 높으신 분들께서 생각이 있으셨겠죠;;하하 미천한 저 따위가 뭘 알겠나요.

이번 항목은 생각보다 별거 없었다.
앞으로 남은 모든 항목이 이런 수준의 난이도라면 참 좋겠어.제길.
Posted by 안식의후크




제목이 뭐랄까 복잡하지만, 내용을 보니 그정도 까진 아닌거 같다.

다형성이라는 정의를 좀 쉽게 설명하면,

"AAA 클래스를 상속받은 BBB 클래스가 있다.
그리고 AAA 클래스의 객체가 BBB 클래스를 접근하는 것이 가능하다. "

라고 표현 할 수 있겠는데...

아.. 써놓고 보니 쉽지 않은거 같기도 하고--;;

자세한 내용은 다형성에 대해서 "객체 포인터"라는 부분에서 정리를 예전에 해 두었으니 해깔리면

그걸 먼저 보는것이 나을 것 같다.

예제는 2가지정도 존재 하지만,
첫번째 예제만 봐도.
"아!... 위험하네." 싶다.


이런 상황이라고 하였을 때,
쉽게 프로그래머의 의도는, AAA arr[10]; 를 만든 이후,
그 값을 출력하기 위해 printAAA 를 만들었다고 보면 되겠다.
하지만,

다음과 같은 상황이 생겼을 때 문제가 발생하는 것이다.
물론 운이 좋게 컴파일러에서 미리 캐치를 해서, 값이 잘 보일 수도 있겠지만.
(실제로 내 컴파일러에서 출력에는 이상이 없긴 했다.)
문제는 delete 라던가, 다른 os나 pc 상황에서 분명 의도하지 않은 결과가 나올 수 있다는 것이다.
AAA의 메모리 크기는 8byte(예상) 라고 했을 때,
BBB의 메모리 크기는 8byte(AAA 클래스의 크기) + 8byte(BBB 클래스의 크기) 라는 것이다.
배열을 +1씩 증가 한다고 했을 때,
8byte씩 삭제 하다 보면,, 나머지 8byte는.. 과연 어디로 증발할지 아무도 모르는 것이다.
물론 BBB라는 클래스가 AAA를 상속받지 않거나, 존재하지 않는다면,
큰 문제가 없을 지도 모른다. 이와 관련되서 추후 항목에 다룬다고 하니, 그 때 다시 한번 확인하여 보자.
Posted by 안식의후크





연산자 오버로딩에 대해 알아 보았다, 하지만 아직 연산자 오버로딩에 대해 완벽하게 알고 있는 것 같진 않다.



그렇다면 저 구문에 대해서 실행을 해주고 싶다면 어떻게 해야 할까?
이런 부분에 대해서는 전역으로 연산자 오버로딩을 해 주어야 한다.


다음은 [] 연산자에 대해서 연산자 오버로딩을 해보자.

비슷한 내용이지만 이번엔 int가 아닌 객체를 직접 저장하는 배열이 존재한다고 하고,
조금 소스를 변경해 보자.

조금 길게 느껴질 수도 있겠지만 큰 틀은 비슷하다.
단지 객체를 담기 위한 클래스와,
배열 안에 들어갈 클래스를 나눈것 뿐이다.
스스로가 스스로를 담기 위해선,
*를 통해서 해야 될 것으로 생각된다.

다음은 대입 연산자(=)를 오버로딩 하는 것에 대해서 살펴 보자.
실제로 연산자 오버로딩이 이루어진 곳에,
p1=p2;
를 하게 되면 p2에 값이 p1으로 이동 된 것을 알 수 있는데,
실제로 이것은 디폴트 대입 연산자 오버로딩? 정도로 표현 할 수 있을 것이다.

어찌 보면 복사 생성자와 같은 맥락이지만,
당연히 기본적인 디폴트 대입 연산자는 얕은 복사가 이루어 진다.
무슨 의미인지 알겠는가?
완벽하게 해주기 위해선,
깊은 복사가 이루어 져야 한다는 것이다.

'프로그래밍 > C++' 카테고리의 다른 글

템플릿(template)  (0) 2010.04.04
임시 객체 생성  (0) 2010.04.04
연산자 오버로딩(operator overlonding)(2)  (0) 2010.04.04
연산자 오버로딩(operator overloading)(1)  (0) 2010.04.04
가상 복사 생성자  (0) 2010.04.03
virtual(가상)  (0) 2010.04.03
Posted by 안식의후크






기존에 존재하는 +, ++, == 등의 연산자를 프로그래머가 중복 정의가 가능하다.

operator+, operator++ 등으로 오버로딩이 가능한데,

멤버 함수내에 선언할 수도 있고, friend 키워드를 사용해서 전역으로 사용 할 수도 있지만,

멤버 함수에 선언해서 사용하는 것에 대해서 먼저 살펴 보자.

연산자 오버로딩의 사용 예,


operator++을 보면 인자를 받지 않고 return *this를 해주고 있다.
설명이 필요 없을지도 모르겠지만, 멤버 함수 내에 선언되어 있는 존재이기 때문에 자신의x,y를 증가 시키고
*this를 넘겨 줌으로써 값을 받아 온다.
만약 *this를 쓰지 않고 return tmp; 같은 식으로 하게 된다면,
++(++p);의 경우,
++p(1증가);
다시 1 증가
총 2증가를 하게 되지만,

복사본을 사용한다면,
++(++p);의 경우,
++p(p의 복사본,1증가);
p의 값은 1 증가,
p의 복사본이 1증가,
결론은 1밖에 증가가 되지 않는다.
다음은 전역에 선언한 operator에 대해서 살펴 보자.

이 처럼 사용이 가능하지만,
가능하면 객체지향적인 코딩을 생각해서 멤버 변수에 연산자 오버로딩을 하는 것이 옳은 방법이라고 생각한다.


그리고 ++p와 p++에 대해서 차이점이 존재한다.
실제로는 선연산 , 후연산이지만 operator를 사용해서는 그 의미가 불문명 해지게 된다.
이럴 경우를 대비해
Point& operator++(); ++p와 같고,
Point& operator++(int); p++과 같다.
예제를 잠깐 보자.

하지만 이 방법에는 큰 문제점이 존재하는데,
위에서 언급 하였던
(++(++p))와
((p++)++)우리가 예상 했던 결과가 나오지 않는 다는 것이다.

연산자 오버로딩이 안되는 경우도 존재 하는데,
. .* :: ?: sizeof 는 할 수 없다고 한다.
마지막으로 주의점에 대해서 이야기 하겠다.
1. p+3;
이 부분은 p의 값들에 3을 더할 수도 있겠고,
또는 p에 3을 더해서 새로운 객체를 생성해서 리턴하는 것일 수도 있다.
즉 저 부분만 봐서는 어떤 일을 하는지 알 수 없다는 것이다. (직접 operator+함수를 보기 전까진.)

2. p+3*3;
연산자는 계산시에 우선 순위가 존재 한다.
만약 저렇게 연산자 오버로딩을 하였다고 하더라도, 순서는 *3 이후 +3을 하게 된다는 것이다.

3. void operator+(int val=10);
이 처럼 연산자 오버로딩은 디폴트 매개 변수를 가질 수 없다. 만약 가능하다면,
p+; 이런 구문이 나올지도 모르고 이는 분명 프로그래머가 원하는 방향은 아닐 것이다.

4. int operator+(int a, int b){ return a+b+3 }
이것 또한 안된다. 연산자 오버로딩을 하지 않은 (int)3+(int)4라는 기본 연산에 대해서 다시 오버로딩을 하는 것은 불가능하다.

마지막으로 전역으로 선언된 연산자 오버로딩과, 멤버 함수로 선언된 연산자 오버로딩은 조금의 불러오는 차이가 존재 하는데,

++p -> 멤버 함수의 경우( p.operator++(); ) 와 같고,
++p -> 전역 함수의 경우( operator++(p); ) 와 같다는 걸 기억해 두자.

'프로그래밍 > C++' 카테고리의 다른 글

임시 객체 생성  (0) 2010.04.04
연산자 오버로딩(operator overlonding)(2)  (0) 2010.04.04
연산자 오버로딩(operator overloading)(1)  (0) 2010.04.04
가상 복사 생성자  (0) 2010.04.03
virtual(가상)  (0) 2010.04.03
함수 오버라이딩(overriding)  (0) 2010.04.03
Posted by 안식의후크