C로도 얼마든지 객체 지향이 가능합니다. by object

트랙백: 절차지향도 훌륭한데, 왜 객체지향인가?

괜히 딴지 및 비판하는 글로 비춰지겠지만 어찌되었던 한 말씀 드립니다.

이제 막 C/C++을 배운 사람이면 트랙백 건 글은 읽으면 많이 도움 되는 내용임에 틀림 없다. 그러나 사람들은 너무나 절차식~, 객체지향~, C는 절차지향~, C++은 객체지향~ 이라는 선입관을 크게 가지고 있는 것 같다. 원글에서 써니님은 아래 C 코드를 절차지향의 관점에서 이야기 하고 있다.

void main()
{
FILE *pFile;
pFile = fopen("hello.txt", "w");
if (pFile != NULL)
{
fputs("Hello Wold", pFile);
fclose(pFile);
}
}

그러나 나는 이 코드가 매우 “객체지향”적으로 보인다.

  • FILE *를 “FILE 구조체에 대한 포인터”로 생각하지 말고 하나의 ‘객체’로 생각하자. 포인터 읽는 방법이라는 글에서도 썼고 불투명 타입이라는 글에서도 썼지만, 어차피 프로그래머는 FILE 구조체의 내부를 직접 조작하는 일이 없다. 표현이 포인터로 되어 있을 뿐 이건 완벽히 ‘객체’와 그 개념이 같다.
  • fopen은 FILE* 객체를 만들어 주는 (요즘 어린 친구들이 디자인 패턴을 굉장히 신봉하는 것 같던데 디자인 패턴 용어를 빌리면) 팩토리 함수라고 보면 된다. C++로 표현하면 생성자와도 유사하다.
  • fputs는 함수를 호출하기 보다는 FILE* 객체에 대한 ‘메소드’로 보면 된다.
  • fclose 역시 FILE* 객체에 대한 소멸자로 볼 수 있다.

똑같은 코드라도 “C는 절차지향”이라는 선입관에 빠져 있으면 코드를 절차지향적으로 읽을 수 밖에 없다. 객체 지향은 언어를 가리지 않는다. C++/C#/Java는 객체 지향을 보다 인간이 이해하기 쉽도록 직관적으로 ‘표현’ 해주는 것에 지나지 않는다. 객체 지향은 언어와는 거의 무관하다. 그 사고 방식은 C 언어에도 얼마든지 적용할 수 있다. 최초의 C++ 컴파일러가 C++ 소스를 C로 변환했던 것을 생각하면 객체 지향이라는 개념은 언어와 큰 상관없다.

 

하나 더 생각해 보자. 아래 printf 코드가 어떻게 보이는가? 컴퓨터에게 문자를 찍으라고 명령을 내리는 것?

printf(“Hello, World!”);

객체 지향적으로 본다면 stdout ‘객체’에 printf라는 ‘메소드’를 실행시키는 것이다. 우리가 쓰는 C 라이브러리도 위에서 언급한 불투명한 타입을 이용하여 매우 객체 지향적으로 만들어져있다. C++ 캡슐화처럼 완벽하지는 않지만 불투명한 타입으로 얼마든지 구현이 가능하다. 예를 들어, Win32 API는 C로 제공된다. 그러나 한번 API를 보면 역시 매우 객체 지향적이다.

HWND hWnd = CreateWindow(...);
SetParent(hWnd, hWndParent);

CreateWindow는 윈도우 객체를 만드는 함수고 SetParent는 부모 윈도우라는 ‘속성’을 바꾸는 메소드다.

 

“에이, 그래도 virtual 함수는 어떡해요?” 라고 물으신다면 역시 이건 virtual 함수의 본질을 모르는 데서 기인한 오해일 뿐이다. C++이 순수 가상 함수로 ‘인터페이스’를 만들 수 있다. C언어는 불가능할까? 가능하다. 왜냐면 가상 함수는 그냥 “함수에 대한 포인터”를 추상화 시킨 것에 불과하다. C언어에서도 얼마든지 C++의 인터페이스를 흉내 낼 수 있다. C struct에 수 많은 함수에 대한 포인터를 선언하면 그게 바로 ‘인터페이스’가 되는 것이다. 실제로 리눅스 커널의 구조체 하나를 보면:

struct block_device_operations {
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
long (*compat_ioctl) (struct file *, unsigned, unsigned long);
int (*direct_access) (struct block_device *, sector_t, void **, unsigned long *);
int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
int (*getgeo)(struct block_device *, struct hd_geometry *);
struct module *owner;
};

이게 뭥미? 바로 ‘인터페이스’다. C++로 표현하면:

class block_device_operations {
public:
virtual int open (struct inode *, struct file *) = 0;
virtual int release (struct inode *, struct file *) = 0;
...
};

이것과 완전히 동일하다. (물론 overriding 이런 건 안 되겠죠)

“에이 그래도 이벤트 핸들러 이런건 힘들자나요~” 라고 물으시면 역시 이벤트 핸들러가 어떻게 구현 되는지 잘 몰라서 벌어지는 사태다. 이벤트 핸들러도 그냥 함수에 대한 포인터, 콜백 함수다. 이걸 가다듬고 추상화한 것이 C#의 delegate과 event이다. Win32 API로 윈도우 프로그래밍을 하면 “event driven”으로 프로그램을 짜야 한다. 메세지 핸들러라는 것이 단순히 WNDPROC이라는 윈도우 프로시저 콜백 함수로 표현되어 있을 뿐이다. 마지막으로 "상속은 안되겠죠?" 상속받을 struct를 멤버 변수로 넣으면 어느 정도 가능하지만 그럴거면 C++을 쓰세요 ㅎ

 

두 줄 요약:

  1. 객체 지향은 프로그래밍 언어와 (거의) 무관한 개념이다.
  2. C++은 객체 지향 언어가 아닙니다. 멀티 패러다임 언어입니다.

(솔직히 프로그래밍 언어론적으로 분류를 한다면 C언어는 절차지향으로 분류가 되기는 됩니다.)

 

p.s. 굳이 딴지 거는 것 같아 말을 하지 않고 있었지만 써니님의 이 글을 보면 큰 오류가 두 개 있다.:

그런데 C 언어에서는 라이브러리에 오로지 함수 만을 저장할 수 있다는 단점이 존재한다. 만일 함수가 전역 변수를 참조하고 있다면 ? 전역 변수의 값을 읽거나 쓴다면 ?, 그 함수는 라이브러리에 포함시킬 수 없게 된다.

이것은 사실이 아니다. 아주 명백한 예를 하나 들면 난수를 만들어 주는 srand, rand는 ‘전역 변수’를 참조하고 있고 이 두 함수들은 C 기본 라이브러리에 매우 잘 포함되어 있다. 좀 더 정확하게 말하면 멀티스레드 환경을 고려해 재진입 가능하게 만들어야 하므로 이제는 ‘전역 변수’, static 변수가 아니라 스레드 로컬 변수로 구현을 하고 있지만 DLL과 정적 라이브러리에 데이터를 export하는 것은 아무런 문제가 없다. (참고 글)

C 언어와 같은 3세대 구조적 프로그래밍 언어에는 ‘전역 변수’를 소프트웨어에서 존재하는 모든 함수에서 변경할 수 있고, 심각한 부작용이 발생하게 된다.

C언어가 전역 변수로 문제를 많이 일으킨다고 말씀하셨는데 이것도 너무 비약된 말씀이다. C++, 자바에서도 얼마든지 남발된 클래스 멤버 변수나 static 변수로 똑같은 문제를 겪을 수 있다. 이건 언어의 문제가 아니라 디자인의 문제일 뿐이다. 클래스 멤버 변수도 누가 변경할지를 명확하지 않으면 개판되기 일쑤다. 함수와 프로시저를 엄격히 구분하는 함수형 언어에서도 어쩔 수 없이 프로시저가 있을 수 밖에 없고, 그럴 경우 전역 변수로 인한 문제는 일어날 수 밖에 없다. C/C++/Java 같은 imperative 언어들은 함수(function)과 프로시저(procedure)를 구분하지 않는다. 프로그래밍 언어 관점에서 함수는 전혀 side-effect가 없어야 한다. 즉, 함수는 주어진 매개 변수만을 조작하여 외부 상태를 전혀 건들이지 않고 값을 반환해야 한다. ‘전역 변수’에 의한 문제점을 없애려면 순수한 함수로, 프로시저 없이 프로그램을 짜야만 할 것이다.

그리고 C언어는 전혀 몰락하지 않았습니다. 앞으로도 몰락하지 않습니다.


덧글

  • Sikuru 2008/11/26 14:45 # 답글

    잘 읽고 갑니다ㅠㅠ

    근데 읽고 나니 쌩뚱맞게도, 이렇게 글을 쓰려면 어떻게 공부해야 할까ㅠㅠ 라는 생각이 문득ㅠㅠ
    뭔가 몸-_-으로 익힌 것들이 많다보니... (한숨)
  • xeraph 2008/11/26 14:50 #

    이론을 잘 공부하시면 됩니다. 전 아직 안 들어봤지만 프로그래밍 언어론에서 잘 다루고 있지 않을까 싶네요. 그 후에 실전에서 이론으로 배운게 어떻게 사용되는지 다양한 경험으로 때우시면 됩니다 ㅋ
  • object 2008/11/26 14:52 #

    네, 프로그래밍이라는 것이 굉장히 사람들이 직접 코딩하고 그런 걸로만 생각하는데 기초 전산 이론이 매우 중요합니다. 방송통신대 TV를 보니 전산학 관련 기초 강좌를 많이 하는데 그런거만 좀 봐도 보이는게 많이 다르실 거라고 믿습니다.
  • Sikuru 2008/11/26 14:53 #

    두분 말씀 감사합니다~ =)
  • xeraph 2008/11/26 14:47 # 답글

    명쾌하게 설명하셨네요 ㅋㅋ 다만 언어에서 세련되게 지원을 안 하니까 너무 귀찮을 뿐이죠.
  • 학주니 2008/11/26 14:49 # 삭제 답글

    C언어가 몰락하면 큰일납니다(^^).
    C언어로만 먹고산지 어언 10년이 다되어가는데(^^).
  • object 2008/11/26 14:54 #

    C언어는 *절대* 안 망한다고 단언할 수 있습니다..
  • object 2008/11/26 14:51 # 답글

    어케 글이 뜨자마자 이렇게 댓글이.. 다들 일 안하시남요? ㅋㅋ
  • Ya펭귄 2008/11/26 15:18 #

    그것이 대한민국 직장생활의 신비....

    업무시간은 쪼들리는데 이글루질시간은 널널한...
  • Ya펭귄 2008/11/26 15:21 # 답글

    C만 가지고 놀다 보니까 저런 개념들을 잘 모르겠더군요... 그냥 이런 식으로 됩니다...

    "아앗~ 구조체에 함수포인터를 잡아놨네~~~ 쓰자~~~!!!" 그리고 끝.

  • object 2008/11/26 16:03 #

    객체 지향 개념은 사실 매우매우 간단합니다. 시간내서 배우시면 몇일이면 될겁니다.
  • 프리윌 2008/11/26 15:27 # 삭제 답글

    좋은글 잘읽었습니다. 객체지향과 프로그래밍 언어는 (거의) 무관한 개념이다라는 말씀에 일면 공감합니다.

    다만 현실의 모습을 좀더 잘 표현(정확히는 좀더 닮아 있는)하는 언어가 갖는 장점이 분명 존재한다고 생각합니다.

    가령 add(3,4)보다는 3+4 가 훨씬 현실의 모습과 닮아 있지 않을까요?
    물론 3.+(4)로 표현해야 하는 경우도 있긴 하지만요 ^^
  • object 2008/11/26 15:53 #

    네, 당연히 맞는 말입니다. 당연히 C로는 객체지향을 흉내내는 것에 불과하지요.
  • C 2009/01/17 17:36 # 삭제

    프리윌, object // ㅋㅋㅋ

    add라... 지금 어셈블리 하고 있습니까?

    3+4는 C에서 그냥 됨.ㅋㅋㅋ ("3"+"4"를 하자고는 많이 하던데...)

    3.+(4)라... (띵~) 산 너머 산... (그닥, 왜 이러고들 있는진 알겠지만...)

    공부를 너무 많이 하면 이렇게 되는 건가? (물론, 3.+(4)도 C에서 그냥 됨. 7.000000 )
    (C는 객체지향 나오기 전부터 연산자 오버로딩, 다형성도 디폴트로 했다능~ ㅋㅋㅋ)


    그닥, 왜 이러고들 있는진 알겠지만, 억지춘향식은 되지 맙시다.

  • novrain 2008/11/26 15:28 # 답글

    임베디드 분야에서는 여전히 "C"를 더 선호합니다.
    뭐 많은 툴들이 C와 비슷한 문법의 스크립트를 제공하는 현실이니... C는 절!대! 망하지 않을것입니다.
    (망하면 제 밥줄이...)
  • object 2008/11/26 15:51 #

    임베디드에서는 C++ 컴파일러가 아주 없는 곳도 있지 않나요. 시간이 지나면서 C언어와 C++은 각각 다르게 진화하면서 각기 다른 영역에서 특화될 것 같습니다.
  • drasley 2016/03/25 12:51 # 삭제

    글이 적힌 2008년 기준으로 적자면.. 임베디드 환경에서도 컴파일러만 교체하면 C++로 컴파일이 됐습니다.
    독하게 마음먹으면 어디든지 컴파일러-컴파일러로 빌드환경을 만들어 쓰면 되니까요.
  • 방준영 2008/11/26 15:53 # 삭제 답글

    얼마든지 할 수 있다고 하기에는 약간 뭔가 쫌...:-) 제 블로그에 같은 일을 하는 프로그램을 C로 짠 것과 C#으로 짠 것을 비교해 둔 것이 있으니 참고가 되기 바랍니다:

    http://junyoung.tistory.com/21
  • object 2008/11/26 16:02 #

    객체 지향을 하기 위해 C언어를 쓰는 바보는 없죠. 다만 C를 써야하는 경우에도 "얼마든지" 객체 지향 개념을 빌릴 수 있다는 것이 글의 요지입니다. C로 C++/C#이 대체한다 이런게 아닙니다 :) Win32 API로 윈도우 코딩하기 위해 윈도우 프로시저 만들고 윈도우 클래스 만들고 등록하고 이런 닭짓을 C# Windows Forms로 정말 깔끔하고 이해하기 쉽게 되죠. 그러나 이것은 '표현'의 문제이고 '개념'은 C언어라도 얼마든지 가능하겠죠. 참고로 Win32 API로도 많이 해봤고 MFC는 소스까지 다 뒤져봤고.. C# Windows Forms도 이와 유사한 클래스 라이브러리를 직접 만들어봤기 때문에 어떠한 차이점이 있는지는 매우 잘 압니다. 암튼 제 글의 핵심은 잘 이해하셨으리라고 믿습니다.
  • object 2008/11/26 16:06 #

    마찬가지로 C++ 0x에 지원되는 람다도 역시 '표현'에 지나지 않습니다. C++의 functor로 구현되는 것이 보다깔끔하고 직관적으로 바뀌는 것이지요. 표현을 무시하는 것이 아닙니다. 매우 중요합니다. 그러나 개념을 표현하는 방법은 여러가지 방법이 있죠. 그걸 어떻게 해석하느냐의 문제입니다.
  • xeraph 2008/11/26 16:22 #

    표현력은 생산성, 코드량, 그리고.. 버그 수에 절대적으로 영향을 미치겠죠? ㅋㅋㅋ
  • object 2008/11/26 16:37 #

    당연하죠. 언어의 표현, 즉 컴파일러의 프론트엔드의 진화는 생산성, 코드량, 버그에 큰 영향을 미치죠. C언어로도 객체 지향 개념을 구현 *가능* 하다는 것이지 효율적으로 구현 가능하다는 것은 당연히 아닙니다.
  • jhumwhale 2008/11/26 16:26 # 삭제 답글

    gtk도 object님이 말씀하시는 예가 될 듯 싶네요..:)
  • object 2008/11/26 16:45 #

    방준영님이 링크 거신 글이 매우 좋은 예가 되겠죠. Win32 API 날코딩으로 윈도우 하나 띄우려면 80줄 이상이 들어가는데, MFC로는 좀 줄고, C#으로는 그냥 몇 줄이면 되죠;;
  • 써니 2008/11/26 16:36 # 답글

    제 글은 늘 오류 투성이입니다... ^^;
    그래도 올리는 이유는 여러 고수님들이 허점을 지적해주시니까요~

    C언어가 몰락했다는 표현은 경솔한 표현 맞습니다. 쓰고 나서 지금 골백번 후회하고 있습니다.

    트랙백 감사 드립니다.~
  • object 2008/11/26 16:44 #

    제 블로그가 기본적으로 높임투가 아니라 평어체라 기분 안 상하셨기를 바랄 뿐입니다 :) 참고로 저는 '고수'나 '하수'로 급을 메기는 걸 썩 좋아하지는 않습니다.
  • 써니 2008/11/26 16:46 #

    쩝... 저도 사람 머리에 등급 매기는 걸 좋아하지는 않습니다.
    다만 감사의 표현으로 적합한 단어를 고르지 못하는 우매함 때문입니다.
    앞으로는 표현을 바꿔보도록 애쓰겠습니다.

    덧글은 남기지 못했지만 자주 들르고 있습니다~
  • 백승우 2008/11/26 17:42 # 답글

    언어마다 남다른 특기가 있기 마련이지요..^^

    쉘스크립트로 객체지향 언어 흉내(?)낸 소스도 봤던 적이 있는데요..
  • monaca 2008/11/26 17:50 # 답글

    이런 논쟁이 나올 때마다 쐐기를 박는 용도로 보여주는 글입니다. ^^;

    - C언어의 범용적인 연결 리스트 구현
    http://monac.egloos.com/1193485
  • object 2008/11/27 16:34 #

    void*는 사실 generic programming입니다.
  • 자연풍선생 2008/11/26 19:01 # 답글

    마지막줄이 특히 와닿네요..
  • eslife 2008/11/26 19:01 # 삭제 답글

    object 님의 글은 늘 시원시원합니다. 가끔은 날카롭고 ^^;
    저도 C++ 을 주력으로 하지만 실제 소스를 보면 C 나 별반 다를게 없는 경우가 많습니다. 제 경우는 아직 공부가 덜 되어서 그렇구요..
    하지만 C++ 을 제대로 사용한다면 C 의 그것보다 이해하기 쉽고 공동작업을 효율적으로 처리할 수 있다고 생각합니다.
    당연히 말씀하신 대로 , 언어 이전에 누가 코딩하느냐가 가장 중요하겠고, 실력이 있다면 원하는 기능을 쉽게 관리 해 주는 언어를 선택하는게 맞다고 봅니다.
  • Lohengrin 2008/11/26 19:50 # 답글

    구조체를 선언한 후에 함수들은 인자에 항상 구조체 포인터를 가지는 구조는 C코드를 보면 실제로 많이 쓰더군요.
  • 몽몽이 2008/11/26 20:06 # 삭제 답글

    객체지향 떡밥이 다시 모락모락 ^^;
    '객체지향' 사상으로 구현하는데 있어서 객체지향 '언어'가 제공하는 진짜 능력은
    상속 구조를 반영한 type checking이라는 생각입니다.
    그거 외에는 말씀하셨다시피 다 그냥 syntax sugar에 불과하죠.

    그나저나... C든 C++이든 살인충동을 유발할 수 있는 언어임은 틀림없습니다.
    모 업체가 10년전에 발로 코딩한 소스를 고치고 있습니다. 평균 10줄당 1건은 버그가 있는 듯.
    문제는 이게 돌아갔었다는...

    그놈의 W/S이 단종돼서 그 후속 모델에서 개발 중인데, 여기서는 짤없이 죽습니다.
    미친듯이 버그를 잡고 있지만 남는게 있으면 이제는... 다 제탓이 되는거죠... T.T

    이런 말 하면 안되겠지만 정말 이 직종엔 삼청교육대라도 하나 만들어야 하는 것이 아닐까요?
  • 김윤수 2008/11/26 21:18 # 삭제 답글

    맞는 말씀! 제가 평소에 하고 싶었던 말을 대신해 주시네요. ^^ (이런 걸 공짜로 버스 얻어타기 전법이라고 하던가요 ?)
  • abraxsus 2008/11/26 23:27 # 삭제 답글

    한가지 덧붙이자.. 내가 하고싶은말은.. C언어에는 global한 전역변수만 있는게 아니라는거..
    모듈별 scope를 가지는 전역static변수/함수가 있다는거지.... -_-;; 많이들 깜빡하시는거 같지만..
    사실 모듈 하나가 클래스 하나에 그대로 대응된다는거..
    모듈별scope가 바로 클래스의 private과 동일하다는거..
    애초부터 C의 (그리고 사실상 시스템전반의) 모듈개념이 바로 클래스와 다를바 없지..
    단지 좀더 dynamic하게 추상화되었다는정도... 그런의미에서 객체지향은 너무 자연스러운 확장일뿐이지..
    흠.. 근데 내통장은 바닥이라는거..ㅠ_ㅠ..
  • object 2008/11/27 16:37 #

    그나저나 module이 여기서 어떠한 의미냐?? module이 워낙 문맥에 따라 의미가 각각이라서 말이야..
  • codewiz 2008/11/27 00:01 # 삭제 답글

    C로도 OOP틱하게 작성하는 사람이 있는가하면, C++로도 어셈틱하게 작성하시는 분들도 계시죠.~
    좋은 글 잘 읽고 갑니다... ^^
  • 모루 2008/11/27 03:45 # 삭제 답글

    C++나 Objective-C 도 초기 버전은 C preprocessor로 구현되었었습니다. DirectX도 같은 인터페이스가 C와 C++로도 제공이 되었었습니다. 제가 본 책중에 Object oriented assembly 라는 책도 있었습니다. 제일 황당했었죠.
  • object 2008/11/27 04:00 #

    MSFT의 COM 객체(DirectX를 포함)를 컴파일하면 생성되는 헤더파일을 보면 #ifndef __cpluscplus 용으로 함수 포인터로 구현된 인터페이스를 볼 수 있죠.
  • sloth 2008/11/27 04:47 # 삭제 답글

    에휴....... 그놈의 OOP
  • lovewar 2008/11/27 09:09 # 삭제 답글

    객체지향에서 보여지는 키워드들이 많이 있지만, object, message 및 class가 대표적인 키워드라 생각합니다(개념적인 이야기라 여길수 있습니다).

    위 세가지 관점에서 본다면 써니님의 예제는 OOP에 대한 예제로 볼수 있습니다
    (리소스 사용관점(할당, 사용, 해제)에서는 두 언어에서 차이는 없는것 같습니다).

    개인적으로 프로그래밍 언어를 사용한다는 것은 나도 모르게 그 중심 사상을 사용한다고 생각합니다.
  • 필넷 2008/11/27 11:56 # 삭제 답글

    '객체지향' 이라는 것은 개념일 뿐이고 그런 관점에서는...

    사실 C++,C#,JAVA 등은 객체지향언어이고 C는 객체지향언어가 아니다라고 구분하는 것도 맞지 않는다고 보여지네요. 단지 언어의 스펙상 어떤것이 조금 더 객체지향 관점에서 만들어졌는가하는 문제인듯...

    객체지향을 이해하는 개발자라면 어떤 언어를 사용하더라도 객체지향적으로 설계하고 구현하고.. 객체지향적으로 해석할 수 있을 듯합니다.

    잘 읽고 갑니다. ^^*
  • 장모군 2008/11/27 13:14 # 삭제 답글

    C 언어의 단점이라고 하면 어떤게 가장 클 까요?
  • object 2008/11/27 16:36 #

    C의 단점은 너무 많아서... 최대 단점이라면 '객체지향적'이지 않다라고 말씀드리고 싶습니다 :)

    좀 더 진지하게 이야기하면 C 언어는 컴퓨터 시스템을 알아야만 제대로 다룰 수 있는 언어라고 생각합니다. 초보자를 위한 언어가 아니죠. 너무 시스템을 적나라하게 드러내다보니 양날의 검이죠. 칼이 너무 좋아 쓱쓱잘 잘리는데 손 베기도 십상이죠.
  • 최익필 2008/11/28 11:32 # 삭제 답글

    예전에 리누스에게 누군가 C++ 로 커널을 짜는게 더 좋지 않겠냐고 제안 했을 때, 리누스는 "무엇 때문에?" 라고 반문 했던 기사가 생각납니다. 많은 사람들이 그 리누스의 반문에 "객체지향적으로 짜기 더 쉬우니까" 라고 대답했던 리플이 기억 납니다.

    지금도 리눅스 커널은 C 듯이, 개발하고자 하는 언어로 얼마든지 객체지향적으로 짤 수 있다는 의미를 갖는거 같습니다.

    글 읽는 재미가 있어 자주 둘러 봅니다~
  • rd 2008/11/28 13:12 # 삭제 답글

    위의 모루님 말씀처럼 C++ 컴파일러는 내부적으로 preprocessor로 C로 변환한 후 실제 컴파일은 C로 다 구현되었죠.
  • object 2008/11/29 07:35 #

    네, 본문에서 저도 언급했습니다 :) 최초의 C++ 컴파일러로 만들어진 헬로 월드가 몇 메가였다는 이야기도 본적이 있군요. 물론 지금은 native C++ 프론트 엔드가 구현되어 사용중이죠.
  • 수아기 2008/11/29 00:43 # 삭제 답글

    늘 글을 읽으면서 제대로 알고 있지 못하면서 무엇인가를 알고 있다고 생각하고 있는 것은 아닌지 하고 제 자신을 돌아보게 됩니다. 그 어떤 언어이든 누가 쓰고 어떻게 표현하느냐에 따라 참 다른것 같아요 특히나 프로그래밍에서는 말이죠.
  • CECRI 2008/11/29 05:25 # 삭제 답글

    사실 프로그래밍 언어 과목 수강하면 대충 알수 있는것인데... 사실 개인적으로 C++에서 제일 좋다고 생각하는건 C에서 객체지향을 확장시켰다느 구조보다는 오히려 template을 통한 generic programming의 지원이죠 ㅎㅎ

    사실 객체지향적 도구도 꼭 필요하긴 하지만 그것을 위해서라면 분명 Objective-C가 훨씬 잘 되어 있는데 굳이 C++쓰는것 자체가 다른 기능들이 더욱 좋아서 라고 생각해도 되지 않을까요 ㅎㅎ

    뭐 원글에 덧붙이자면 프로그램 언어 자체가 주로 여러 패러다임이 있고 어떤 프로그래밍 언어를 잘 다룰려면 그에 깔린 패러다임의 철학을 알아야 한다고 생각합니다. JAVA를 잘하려면 분명 객체지향적 사고가 박혀있어야 하고 함수형 프로그램 언어(Scheme, ML, Haskell)를 쓴다면 lambda 함수같은것에 익숙해야 하고 Ruby를 잘쓰려면 에자일 프로그래밍을 얼마정도는 알아야 하고 뭐 그런것들 말입니다. 사실 제일 어려운건 prolog같은 논리형 언어죠. PL시간에 배울때도 당최 무슨철학으로 만든 언어인지 헷갈려 하던 기억이 나네요.

    다른 패러다임과는 조금 다르게 객체지향은 사실 언어의 철학보다는 설계의 문제가 되곤 하지요. 예로 함수형 언어인 LISP을 확장해 객체지향언어인 CLOS를 만들수도 있으니까요. 게다가 WINAPI는 설계만을 통한 객체지향을 잘 보여주는 예라고 생각합니다. 윈도우 클래스와 서브클래싱 등등을 보면 뭐 API 자체가 하나의 새로운 객체지향 언어를 만든다고까지 볼 수도 있을듯 합니다. 하지만 분명 객체지향이라는 것도 철학이 있는 패러다임이고 그에 대한 철학으로 구현된 언어가 많이 있습니다. 그러한 언어들을 만났을때 비로소 객체지향이 날개를 달고 날아갈 수 있는듯 합니다. JAVA같은 경우는 조금 모자라지만 Ruby나 또는 Smalltalk같은 경우를 보면, 그러한 특징들을 잘 볼수 있죠. 엄청 깔끔한 객체지향을 볼 수 있으니까요.

    사실 실제로는 이러한것은 다른 패러다임도 그닥 다르지 않습니다. C++에서 functor를 통해 함수형 언어처럼 사용하는 방법을 보면 절차지향과 함수형 언어도 사실 설계상의 문제까지 내려 갈 수 있을듯한 단서가 보이죠. 게다가 처음에는 일반적인 타입을 위해서 만든 템플릿을 통해 함수형 언어처럼 컴파일 타임에 동작시키는 것을 보면 함수형 언어도 사실 별거 아니라는 것을 깨닮을 수 있습니다. 하지만 함수형 언어가 함수형 프로그래밍을 하는데 더 편할 뿐만 아니라 언어 자체에서 제공되는것들이 그러한 철학을 내포하고 있어서 다른 느낌이 나게 되죠. 이것이 함수형 프로그래밍 언어를 쓰는 이유가 되겠죠.

    사실 프로그래밍 언어론적으로 놓고 생각하면 C/C++은 별로 좋은 점수를 못받는 언어입니다. 최악의 표현력에 표현력을 높인 C++도 오만가지 패러다임을 섞어서 뭐가 뭔지 알아볼수 없게까지 만들어놨죠. 하지만 10년 내에 없어질 가능성이 하나도 없는 언어입니다. 사실 중요한것은 C로 객체지향이 되냐 안되냐 보다는 프로그래밍 언어의 기본적인 사항을 알고 적절한 것을 선택하는것이 중요하다고 생각되네요. C로 객체지향을 한다고 해도 C코드는 C코드지 Ruby코드가 될수는 없는것이 아니겠습니까?
  • object 2008/11/29 08:45 #

    어떤 언어가 성공 하냐 안 하냐는 PL 이론적인 관점 따위는 큰 영향이 없습니다. 얼마나 많은 업계가 실제 프로젝트에서 이 언어를 사용하느냐, 얼마나 많은 사람들이 사용해서 많은 경험이 축적되어있느냐 그런 것에 달려있습니다. C/C++은 10년이 아니라 50년 내에 없어질 확률도 거의 0%로 수렴합니다. CPU 차원에서 ISA가 급변하지 않는 이상 C는 절대 안 망하고, C++도 안 망합니다. 망할 것 같으면 얘들은 진화하여 새로운 모습을 수용할 것입니다. 단적인 예로 C++ 0x의 람다 수용을 보면 알 수 있죠. C/C+에도 얼마든지 가비지 컬렉터가 들어갈 수도 있습니다. 이미 연구도 많이 되었고요. 컴퓨터 업계는 생각보다 굉장히 보수적입니다. 10년전 VC6을 쓰는 사람이 아직도 허다하고 20~30년 된 코드도 지금 쌩쌩하게 돌아갑니다. 아직도 포트란으로 코딩하는 사람 많습니다. 그리고 C코드는 C코드죠. C코드가 C++이 될 수도 Ruby가 될 수도 없죠 ㅎㅎ
  • abraxsus 2008/11/29 17:02 # 삭제 답글

    ㅎㅎ.. 이런 주제 뭐... 상당부분 주관적이니 많은말들이 있겠고, 그만큼 뭐 생각할만하기도 하고..
    어떤분께서는 아래처럼 C로 higher-order programming 을 할수도 있다고 예를 보여주시고싶어하시지...
    ㅎㅎ...

    http://www-128.ibm.com/developerworks/library/l-highfunc.html

    뭐 scheme광고글처럼 보이긴한다만,..(PL쪽도 참 interesting하긴 한데..말이지..)
    글구 C에서 모듈은 그냥 .o 화일..즉 .c화일 하나가 하나의 모듈임.. 그걸 우리가 링크하는거니까..
    그래서 모듈에 하나의 기능씩 구현되고 모듈별로는 local scope가 있어서.. private member인셈이고..
  • 네코 2009/01/08 02:20 # 답글

    C언어 배우면서 몇 가지 궁금했던 부분들이 이글로 풀렸네요.
    감사합니다. _ _
  • C 2009/01/18 14:11 # 삭제 답글

    C++가 객체지향 언어로 분류되는 것들 중에서 젤 어렵다고 들 합니다.


    C++는 원래 객체지향 프로그래밍을 위해 설계된 언어가 아니고, C언어를 능수능란하게 다루는 고수들이 C언어로 즐겨쓰던 현란한 기법을 그대로 정리하여 반영한 것으로 보는게 적절합니다. 이렇게 C언어 고수들이나 즐겨쓰던 용법을 반영하다 보니 구문 자체가 어려운 것 입니다. 사실 객체지향 프로그래밍 언어는 인간이 이해하기 쉽자고 하는 언어인데 말이죠. 여기서 인간은 물론 일반 프로그래머를 말합니다. 당연히 C언어 고수들에게는 별로 어렵게 느껴지지 않겠지만 아니, 자주 봐 와서 오히려 더 손과 눈에 착착 붙었을지도 모를 일이지만 말입니다.


    당시 고수들은 대체로 (지금의 class 처럼 사용한) struct와 함수포인터를 섞어서 쓰면서 일반 개발자들이 보면 혀를 내두르게 하는 기상천외한 소스코드를 작성하였습니다. 그 구문의 쓰임새로 말하자면 마치 지금의 객체지향 프로그래밍 용법과 거의 다를 바가 없었습니다. 또한 당시 고수들은 여러 프로젝트를 섭렵하면서 자신만의 함수 라이브러리를 축적해 왔는데 이러면서 다음 프로젝트 규모가 점점 커져감에도 불구하고 개발기간이 느려지기는 커녕 개발속도가 빨라졌습니다. 그러다가 아예 맘먹고 자신의 라이브러리를 시간을 들여 세련되게 가다듬어가다 보니 소스코드의 캡슐화도 재사용성도 자연스럽게 녹아들어가 반영된 것입니다.


    이와 같은 상황에서 볼때, C++ 언어를 객체지향 프로그래밍 언어로 설계된 언어라기 보다는 고수급 C언어 사용자를 위해 맞춰진 향상된 C언어라고 보는게 맞고, 이 과정에서 C언어 고수들이 즐겨쓰던 수준 높은 프로그래밍 스타일이 집적되어 자연스럽게 반영되던 것이 그대로 객체지향적 특성을 담게 되었다고 보는게 맞습니다. 즉, C언어의 단점을 보완하거나 뭔가 새롭게 개선했다기 보다는 C언어 고급 사용자의 수준 높은 사용 스타일에 맞춰져 잘 반영된 커스터마이징이라고 봐야합니다. 이렇게 딱히 어떤 지향하는 목적에 따라 처음부터 새롭게 설계되었던게 아니다 보니 C++ 언어가 세상에 나온 뒤에 그제서야 접한 많은 사람들이 언어의 정체성을 딱히 규정하지 못하기도 합니다. 이런 이유 때문에 결과적으로 C++언어가 객체지향적 특성을 어느 정도 갖고 있지만 일반 프로그래머에게는 상당히 어려운 언어가 된 것입니다. 사실 당초 C++가 객체지향적 프로그래밍 언어로 설계되었다면 일반 프로그래머에게 이렇게 읽히기 어려우면 안 되는 겁니다. ^^*


    흔히 객체지향하면 일반인들은 쉽게 Java를 많이 떠올리는데, Java도 탄생 당시 스스로도 C/C++ 구문체계에서 모사했다고 실토했고, 게다가 C++에서 불필요하고 복잡한 문법을 과감히(?) 생략했다고 까지 언급하였습니다. 제가 보기에는 그렇지 않아도 Java가 플랫폼 독립한답시고 속도도 느린데다, 생략했다는 그 문법이 사실 구현도 까다로워서 깔끔하게 무시했다고 판단했습니다. 당초 플랫폼 독립을 모토로 시작했지만 플랫폼 독립은 고사하고 동일 플랫폼에서 가상머신 버전만 틀려도 안 맞으니, 지금은 그 말이 쏘옥 들어가 버리고 엔터프라이즈 컴퓨팅이 대신 나와 있습니다. 최근 엔터프라이즈 영역에서 개발수요가 많고 초기 썬의 자바교육 커리큘럼이 잘 돼 있어서 많이 읽히니까 눈에 익어서 가독성이 좀 있을 뿐 입니다. 그리고 우리는 Java 창시자도 C/C++ 고수였다라는 사실을 직시해야 합니다. 그러니 Java 창시자야 원래 나름 읽기 쉬웠겠지만, 이런 이유들 때문에 Java 또한 객체지향언어가 지녀야할 가독성이 부족한 건 사실입니다. 물론, C++ 보다야 가독성이 수월하기는 하지만 말입니다. 비록 그것이 구현이 어려워 생략의 미덕이 가미된 것 일지라도 말입니다.


    객체지향적 프로그래밍 언어 하면 모델링이니, 재사용성이니, 캡슐화니, 다형성이니, 하는 말은 많은데 결국 모두 이를 통해 가독성을 우수하게 만드는 것으로 귀결됩니다. 제가 가독성, 가독성, 하니까 느려 터지고 안되는 거 많아 백치미 자랑하거나 육중한 실행파일 생성하는 컴파일러 들고 와서 여기 있다고 그러면 안 된다능~. 자, 이제 본격적으로 진정 제대로 된 객체지향적 프로그래밍 언어가 세상에 나올 시점이지 않습니까?

  • jokerol 2009/09/28 10:41 # 삭제 답글

    제 위의 분 말씀중 초창기 C++ 태생의 기원에 대해 공감합니다.
    원래 c++의 초창기 명칭이 c with class 였다고 알고 있습니다. 말 그대로 클래스를 쓰는 C였다고 들었습ㄴ다. 그후에 현재와 같은 모습을 갖추었다고 알고 있는데, 말씀대로 초창기에는 기존 뛰어난 C 개발자들이 쓰던 객체지향적 기술들을 일반인(ㅋ _ ㅋ)이 사용하기 쉽게 언어적 차원으로 포함했다는 말이 매우 재미있었습니다.

    그런데 원본 글에 보면

    '이것과 완전히 동일하다. (물론 overriding 이런 건 안 되겠죠)'

    라는 내용이 있는데, 오타 아닌가요? 오버로딩 같은데..
    함수 포인터로 불러올때 마다 상황에 맞는 함수를 부를 것이므로 함수가 오버라이딩(재정의) 된거죠.

    아마 오버로딩(인자를 통한 분별력으로 함수를 호출하는 것)과 오버라이딩이 용어가 상당히 비슷한 지라 오타가 난 것 같네요.

  • object 2009/09/28 11:50 #

    최초의 C++ 컴파일러는 C코드로 바꾸어주는 프론트엔드 컴파일러였죠.

    제가 의도한 것은 오버라이딩이 맞습니다. 말그대로 함수 포인터 덩어리 struct로 오버라딩을 손쉽게 구현할 수 없기에 한 말입니다.
  • 박재현 2016/03/25 12:56 # 삭제 답글

    안녕하세요. 페북 C++ 클럽에서 가끔 뵙다가 블로그 방문했습니다.
    읽을거리도 많고, 취향에도 잘 맞는 글들이라 시간날 때 마다 정주행 해볼까 합니다 ^^ 다 읽고나면 깃헙에서 또뵙죠~ ^^
  • PleYa 2016/07/06 23:13 # 삭제 답글

    글 재밌게 보고 갑니다 :)

    저도 C로만 프로그래밍을 하다보니, C와 C++(객체지향)의 차이가 뭘까 고민했었는데,
    글을 읽어보니 재미있네요.
  • fullop 2016/07/13 22:46 # 삭제 답글

    독학으로 C 끝낸 후 C++ 공부하는데 잘 읽고 갑니다~
댓글 입력 영역