OOP in C

C에서도 객체지향적으로 코딩을 할 수가 있다. 
하지만 C자체적으로 객체지향을 위한 키워드나 문법을 지원하지 않으므로 억지스럽고 비효율적인 측면이 있고 불가능한 부분도 존재한다.

객체지향의 핵심은 무엇일까?
1. Class (데이터 + 메소드) 와 캡슐화
2. 정보 은닉 및 추상화
3. 상속
4. 다형성
난 이 4가지가 객체지향의 핵심적인 개념이라고 생각한다.

일단 C에서 Class (데이터 + 메소드) 와 캡슐화의 개념을 implementation 하려면 설계를 객체지향적으로 하면 된다.
Class같은 경우는 데이터는 구조체 안에 넣고, 메소드는 구조체이름_메소드이름 (구조체 포인터, ...) 이런 형태로 하면 된다... 만약 함수포인터를 이용하면 C++같은 문법으로 메소드를 사용할 수 도 있겠지만... 객체 만들때마다 함수포인터들을 초기화해줘야하므로 별로인 방법 같다.

추상화나 정보 은닉 같은 경우는 파일 분할과 static을 이용하면 가능하다.
아래에 그 예제가 있다.

blackbox.h
blackbox.c
main.c
main.c에서 6번째줄의 주석을 풀면 위와 같은 에러가 난다.
main.c입장에서는 struct blackbox가 있다는 것 만 알지, struct blackbox 내부 구조를 모르므로 
그 크기를 모르기 때문에 변수를 만들수가 없다.
따라서 포인터를 사용해야한다. 포인터는 무조건 크기가 정해져있으므로 타입에 상관없이 변수를 할당할 수 있다.

main.c에서 11,12번째 줄의 주석을 풀면 위와 같은 에러가 난다.
위에서 설명한 바와 같이 struct blackbox 내부구조를 모르므로 dereferencing이 불가능하다.
따라서 11,12번째줄에서 에러가 난다.

실행결과는 위와 같다.

위 코드에서는 성공적으로 private variable과 private/public method, 그리고 생성자와 소멸자를 구현했다.
하지만 제한점이 있다. 
첫번째로 객체생성이 무조건 동적할당을 통해 이루어져야한다는 점이다.
구조체의 크기와 내부구조를 모르므로 객체(구조체)생성은 무조건 blackbox.c에서 이루어져야한다.
따라서 동적으로 생성될 수 밖에 없다.
두번째는 private variable과 public variable이 공존할 수 없다. 하지만 정보은닉과 추상화의 입장에서 public variable을 쓰지 않는 것이 좋으므로 크게 단점이 되지 않을 것 같다.

그러면 OOP의 다른 측면을 살펴보자.
상속이나 다형성 같은 경우는 C에서 완벽하게 구현하기는 불가능한 것 같다.
상속을 구현하려면 derived structure안에 base structure를 넣는 식으로 할 수 있겠지만 base의 method는 어떻게 호출시킬 것인가? derived에 base method의 wrapping method를 추가해야할 것이다. 
애드혹 다형성 (함수 오버로딩) 은 C에서 문법적으로 지원을 안하므로 굳히 비슷하게라도 하려면 ~~~_1 , ~~~_2 , ~~~_3 이런 방식으로 하면 될 것 같다... 파라미터 다형성 (탬플릿) 같은 경우도 C에서 문법을 지원하지 않지만 굳히 만약 하려면 구조체 이름을 ~~~_int , ~~~_double 뭐 이런 식해서 여러개를 만들면 그럴 듯 할 수 도있겠지만... 쓰레기 같을 것같다...;;
즉 애드혹 다형성이나 파라미터 다형성은 문법적인 이유로 C에서 구현하기에 불가능하다고 봐도 될 것 같다...
서브 타입 다형성을 구현하려면 자체적으로 v-table을 구성해서 하면 가능하긴 할 것 같다...(굳히 이렇게 까지해서 사용할 필욘 없을 것같지만...)
interface같은 경우는 함수포인터로 이루어진 구조체로서 구현이 가능할 것 같다.

댓글