[C] 객체지향적 C: 메서드의 구현

[원본 링크]

C는 기본적으로 객체지향적 문법을 제공하지 않는 단순 절차적 언어다.
하지만 객체지향의 원리를 잘 알고 꼼수를 쓴다면 C로도 객체지향적 코드를 짤 수 있다.

객체지향에서 클래스는 속성과 행동을 가져야 한다. 일단 속성은 구조체로 해결이 가능하다.

좌표값 x와 y를 가지는 클래스 Point를 만들어본다치면 일단 이렇게 될 것이다. image

image


그럼 행동은 어떻게 구현해야할까?


방법 1: 함수포인터를 박는다.
C는 다행스럽게도 함수를 값으로 다룰 수 있는 방법을 제공한다.

함수포인터를 이용해, 자신의 값을 형식화해서 출력하는 print 메서드를 구현해보자.

함수포인터를 구조체에 넣고, 그에 맞는 함수를 따로 구현해서 객체 생성시에 집어넣으면 된다. image

image 잘 돌아가는걸 볼 수 있다.
메서드의 첫번째 인자로 자기자신을 보내야 하는건 어쩔수없다.
문법에서 지원이 안되는걸 어쩌겠나.

근데 저기서는 메서드가 하나뿐이라 덜하지만, 생성할때마다 함수를 집어넣어야 하는건 굉장히 번거로운 짓이다.

대신 함수를 매칭해주는 생성자 함수를 만들어보자. image

image 나는 그럴듯해보이게 하려고 new_로 지었는데, 취향대로 하면 된다.

만약 struct를 typedef로 떼지 않을 거라면, 생성자명을 클래스명과 동일하게 맞출수도 있다. image

image

그리고 위의 코드들에선 그냥 최대한 간단하게 짜려고 그냥 값 객체로 생성해서 반환토록 했지만, C는 반환값 최적화가 되지 않기 때문에 불필요한 복사가 발생할 수 있다.

이점을 유의해서 복사를 피하고 싶다면 동적할당을 해서 반환하든지, 아니면 그냥 포인터를 전달받아서 연결해주도록 하자.


방법 2: 함수테이블을 만들어서 박기
위의 방법은 보기엔 나쁘지 않지만, 함수포인터라는 변수를 다수 집어넣는다면 불필요한 메모리의 낭비와 복사를 유발할 수 있다.

예를들어, Point의 객체 p, p2, p3...들을 만들어도, 이 객체들이 가지는 메서드는 의미론적으로 같지 않은가?
그럼에도 불구하고 위의 방법은 객체를 생성할때마다 함수의 변수들이 새로이 생성된다.

이를 막고자 한다면, 이 함수에 대한 테이블 객체를 정적으로 생성해놓고 바인딩하면 된다. image

image 코드 양이 좀 늘어나고, 메서드 호출 중간에 테이블에 대한 접근이 추가된다는 것이 단점이다.


상황에 따라, 취향에 따라 골라쓰면 된다.