Overloading은 과적, Overriding은 덮어씀이다.
과적이란 말은 말 그대로 하나의 의미적 컨테이너에 서로 다른 개념체들을 실어놓는걸 말한다.
다음 낯선 두 남녀의 대화에서 Overriding 과 Overloading 을 찾아보자.
* * *
남자 : 당신과 대화를 나눠보니 즐겁네요. 실례지만, 우리 사귈까요?
여자 : ( 놀라며 ) 저도 즐겁긴 한데, 만난지 한 시간도 지나지 않았는데 사귀다니요.
남자 : 서로 잘 알면 사귈 필요가 없겠죠. // 기존 개념의 erasing
호감 가는 사람끼리 서로를 잘 알아 가는 과정이 사귐 아닐까요? // re-definition
여자 : 음... 그 말이 틀린 말은 아닌데... 음... 그럴까요?
// 동의를 얻음 ( warning 은 있었지만 error 는 아니니 compile 되었다 )
남자 : 이제, 음 우리 사귀기로 했으니 전화번호 주세요. // override + overload
있다가 연락 드리죠. // management
* * *
일단 해킹이 되고 "남친"의 권한( permission )을 얻으면
그 뒤 만남의 횟수, 연락하는 빈도, 장소 이런것들 마음껏 정의 가능 ( use )
"사귐" 의 사전적 의미는 다양한 관계와 케이스를 내포하고 있다.
즉 overload 되어 있다는거다. 모든 단어가 그렇듯 말이다.
위의 대화에서 남자는 가벼운 의미의 ( 친구의 ) "사귐" 을 꺼내 상대에게 기본 권한을 얻은 뒤
이성이라는 type 간의 특성을 이용해 자연스레 무거운 의미의 ( 연인의 ) "사귐" 으로 바꾼다.
결과적으로 override 해버린 것이지.
이렇게 overload 와 override 는 일상에서 흔히 벌어지는 이데올로기적 개념이다.
실체가 아닌 개념이지만, 개념이 곧 실체임은 공즉시색 색즉시공인 셈인것이지.
즉, 니가 훌륭한 프로그래머라면, 이성도 해킹하고 재 프로그래밍 할 수 있다.
C++ 에서의 overloading 은, 함수와 연산자의 경우로 나뉜다.
행위는 비슷한데, 선언/정의 뒤 사용하는 방법이 조금 다르다.
함수 오버로딩인 경우 동일 함수명에 다양한 타입을 지원하는
"다형성"의 개념적 일부를 사용하고 있다.
class SOME_CLASS
{
auto some_function( int );
auto some_function( char* );
};
같은 표현이 있을 때,
실제로 컴파일러는
SOME_CLASS::some_function@int 라는 이름과
SOME_CLASS::some_function@char* 라는 이름을 갖게 되는 셈이다.
namespace 로 싸 뒀다면 하나가 앞에 더 붙는 식이지.
하나의 이름으로 접근하면 된다는것은 개발자의 기억장소를 줄여준다. 개념적으로 단순화된다.
그래서 바람직하다. ( 문제가 거대해 보이면 풀 수 없음. 솜뭉치도 1톤이면 깔려죽음 )
가져다 쓸땐,
어떤회사::어떤조직::이름::어떤직함 이 아닌 그냥
김 이사님. 처럼
SOME_CLASS some_instance;
some_instance.some_function( ... );
처럼 쓰면 되는 것. 타입이 바뀐다 해도 이름은 변하지 않는다.
변하지 않아서 단순한 것이다.
연산자 오버로딩의 경우는
class SOME_CLASS
{
auto operator==( const SOME_CLASS& );
};
처럼 작성된다.
이러면 내부적으로 함수의 경우와 마찬가지로,
SOME_CLASS::operator== 라는 이름의 함수가 생긴다.
다만 가져다 쓸때,
SOME_CLASS one, another;
if( one == another ) ...
처럼 연산자를 바로 사용할 수 있다는 것이다.
컴파일러가 단항( unary ) / 이항 ( binary ) 연산자를 발견하면
알아서 필요한 항을 ( 앞 뒤로 )참조해 그 항의 타입에 소속된 멤버 연산자로 연결된다.
연산자는 영어 단어보다 더 작고 직설적인 개념이다.
그래서 바람직하다.
연산자 overloading은 사실 의미적으론 override 되는 셈이다.
같다나 덧셈 같은 연산자의 본연의 역할과는 다르니까 말이다. ( 전혀 상관없는 출력문을 넣을 수도 있다 )
연산자 overloading 은,
원래의 연산자가 가지는 의미를 최대한 승계할때가 바람직한 사용이다.
엉뚱한 기능을 사용하면 의미적으로 커진다. 즉, 바람직하지 않다. 직관성이 떨어진다.
그러면 C++ 에서 override 는 무엇인가.
그 밑에 깔려 지워진 개념체가 존재하는 경우에 오버라이드라는 단어를 사용된다고 생각하면 된다.
추상클래스나 부모 클래스의 멤버 함수를 자식 클래스에서 다른 기능으로 재정의할 때 사용하는 것이다.
위의 두 남녀의 이야기를 떠올려보자.
결국 어거지로 올라탄 override 는 지속성이 없다.
좋은 설계는 충분한 시간이 필요하다.
네가 설계한 부모 객체와 자식 객체는 충분히 서로를 알아갈 시간이 필요하다.
이 개념은 또한 여러분 안에서
충분히 녹아들 시간이 필요하다.
아~ 알 것 같다.
에서 멈추지 않는 것.
그 태도가 당신의 소스코드의 수명을 연장해줄 것이다.
그래서 인간이란 포유류는 세상에 나오기전에 어머니 뱃속에서 열달동안 디자인 되는 것.
어머니로부터 ( 상속되어 ) 태어난 아들은 또 다른 여성을 어머니로 만들기 위해 override 한다.
C++ 은 이치에 맞다.
즉 하나의 침대에 두 사람이 올라가는건 overload고, 정상위가 override 다.
컴파일러 과목은 이런것과 관련된 과목이 아니지만... 뭐 어쨌든 : )
흠 뭔가 심오하네요....
연산자 오버로딩은 이름이 좀 정확하지 않다는건가요? 오버라이딩 처럼 될수가 있어서?
결론은 재사용성이 높은걸 만들자!
오버로딩은 과적인데 연산자 오버로딩은 기존의 기능 (의미) 를 싹 밀어버리니 과적이라기 보단 오버라이딩이란 소리죠.
다만 상속되는건 연산자 기호로 연상되는 보다 추상적인 의미와, 단항연산자라 하나의 operand ( 여기선 개체 ) 를 갖느냐 이항 연산자라 두 개의 operand 를 갖냐 정도의 형식 밖에 없으니까요.
하지만 아무 연산자나 전혀 상관없는 기능을 위해 가져다 쓰는건 직관성에서 바람직하지 않고, 의미적으론 연산 원래의 추상적 의미를 따르기 때문에 overloading 의 형태로 사용하는게 바람직하다는 이야기 였습니다.
감사함니닷
코세형 사람 만날 때마다 저렇게 들어옴?
원래 연산자는 오버라이딩이라 부르지 않나?
아, 오버로딩이 맞네. 그냥 오버라이딩이라고 생각하고 있었는데. 근데 그냥 둘 다 결합된거 같지 않음? 오버로딩도 있을건데...
와... 진짜 얼마나 개념에 깊이가 깊어져야... 이런것으로 example 을 할수가 있을까요..