사실 C++에서 객체지향은 그렇게 까지 큰 부분을 차지하고 있지는 않다. 스캇 마이어스 형님의 EC++에서는 C++은 절차형 언어, 객체지향형 언어, 제네릭 프로그래밍, STL이라는 네가지 부분으로 나눌 수 있다고 한다. 사실 STL은 라이브러리일 뿐이지만, 그 자체만으로도 엄청난 성능을 자랑한다. 웬만한 알고리즘과 자료구조는 전부 있으니 STL을 잘 아는 사람이 짠 수치계산이나 통계같은것의 코드는 전부 STL만 쓰여서 그냥 STL코드라고 불러도 될정도니 그렇게 포함시킨것 같다.

C++에서 객체지향은 그것을 이루는 네가지 구성요소중 한가지에 지나지 않는다. 여기서 자바와의 차이점이 발생한다. 하지만 이로 인해 생기는 오해가 C++을 java보다 못하다고 생각하는것이다.

많은 사람들이 C++의 객체지향정도가 많이 낮다고 한다. 이것에 대해서는 나도 어느정도 동의하는 편이다. 하지만 이것을 가지고 C++을 깍아내리는건 바람직하지 못하다. 여러 라이브러리나 이런것이 비 객체지향적으로 설계되어 있지만 그 이유는, 어느 경우는 템플릿을 쓰는것이 재사용성이나 간결함을 객체지향을 쓰는것보다 훨씬 잘 구현할 수 있기 때문이다.

C++에서 자바의 Object같은것이 없는 이유는 그런것을 통해 클래스 계층구조를 만듬으로써 잃는 성능상의 이점이 얻는것보다 많다고 느꼈기 때문일 것이다. 사실 Object같은건 프레임워크에서 구현할수 있는 것이고(MFC의 CObject가 그렇다) 보통의 경우 그것을 쓰지 않아도 충분히 코드를 만들 수 있고, 필요한 경우에도 템플릿 같은것을 쓰는 경우가 더 효율적일때가 많다.

사실 객체지향을 배우기에는 C++은 별로 바람직하지 못하다. C++의 원래 목적은 뛰어난 프로그래머에게 강력한 툴을 제공하기 위한것이라고 한다. 사실 C++의 복잡한 문법과 템플릿의 능력같은것을 보면 그 말이 틀리지는 않은 것 같다. 처음 객체지향을 배우는 사람이 C++의 방대한 문법을 본다면 꽤나 암담할 것이다.

그리고 많은 사람들이 JAVA를 객체지향적이라고 하지만, 자바의 객체지향은 C++의 부분집합이라는 느낌이 강하다. 물론 레퍼런스나 가비지 컬렉팅 같은것은 C++과의 뚜렷한 차별성을 주지만, 기본형과 객체의 구분과(오토박싱이 있긴 하지만 그래도 다른것은 다른것이다) '.'연산자로 메쏘드에 접근하는것은 사실 완벽한 객체지향이라는 smalltalk에 비추어 보면 그 정도가 모자란다. 사실 자바가 쓰기가 편하고 간결한것은 부정할수 없는 사실이다. 하지만 그 이유가 객체지향을 완벽히 구현했기 때문이 아니라, 사용자에 맞추어 개발된 언어기 때문이라는것이 내 생각이다.

smalltalk, ObjectC같은 메세지 기반으로 객체지향을 구현한 언어들을 보면 놀랄만큼 유연하다. smalltalk는 객체지향이 언어에 완벽히 내제되어있다(C++처럼 C에 문법을 추가해서 구현한 객체지향과 다르다는 이야기이다). 레퍼런스는 어느 타입이나 가리키고 메쏘드 호출은 메세지를 보내는것으로 대신한다. 가상함수나 이런것으로 구현된 오버라이딩이 아니라 메세지 처리기만 바꾸는 방식이다. 하지만 별로 인기가 없는것은 그만한 메리트가 없다는 것이겠지.

사실 WIN32API도 메세지 기반으로 C에서 객체지향을 구현하기는 했다. 하지만 언어가 아닌 관계로 언어의 문법 대신, 여러가지 API함수들을 통해 객체지향을 구현한다. 따라서 그닥 쓰기 쉽지가 않다. 객체지향적이긴 하지만 쓰다 보면 MFC가 왜 나왔는지 알수 있다.

다시 C++로 돌아오면 C++에서는 객체지향을 강제하는것이 하나도 없다. 라이브러리가 특별히 객체를 요구하지도 않는다. 그냥 함수객체같은것은 함수 포인터면 된다. 하지만 이것이 다른 방향의 객체지향을 만든다. smalltalk가 기본형과 객체 구분없이 레퍼런스로 가리킨다면, C++은 객체를 아예 기본형처럼 만든다. 객체는 수치형이 될수도 있고, 그냥 우리가 아는 그냥 객체일수도 있고, 아니면 함수객체같은것 일수도 있다.

사실 C++이 완전히 이렇지는 않다. 객체형을 받을때는 const T&로 받고 기본형은 그냥 값에의한 호출로 받기 때문에 차이점이 아예 없는것은 아니다. 하지만 제네릭 알로리즘 같은것은 C++의 이런 부분을 남김없이 사용할수록 되어 있다. 대충 알고리즘에서 사용하는 연산자들만 지원하면 어느 타입이든 전부 된다.

JAVA에서는 이런것을 따라하기 위해 객체지향적인 방법을 사용한다. T Max<T implements Comparable>(T[]) 같은 식이다. 하지만 이런것에서 T는 레퍼런스로 한정되어 있다. 기본형은 오토박싱을 써야 하고, 이런 제네릭은 TMP같은것도 불가능하다. 구현 자체도 JAVA에서는 T에 대해 compare메쏘드를 호출하는 식으로 비교한다. C++에서는 >연산자이다. 연산자 오버로딩의 강력함이다. 결국 함수 호출이 되지만 기본형에서도 잘 작동하고 무엇보다도 이런것을 통해 가벼워진다. 이런 식으로 C++은 객체지향을 포기하지만 강력함을 포기하지는 않는다.

사실 C++은 사용하기 어렵다. C++찬양을 하던 나도 별로 쓰고 싶지 않은 경우가 많다. 메모리관리를 직접 해야 하는건 정말 성가시다. java에서는 별로 필요 없는 pimpl 관용구를 써야 할때도 많다. 하지만 그래도 자바에서는 느낄수 없는 STL이나 템플릿의 강력함, 연산자 오버로딩, 스택에 쌓이는 객체 등은 정말 색다른 매력이다. 특히 자바에서 펑펑 낭비해가면서 쓰던 메모리를 C++로 돌아오면 조심조심 쓰는 그런 이중적인 모습도 발견할때 마다 웃게 된다 ㅎㅎ. 뭔가 java에서는 인간적 느낌이 별로 안느껴 지는듯.