C언어로 객체 지향 Class 흉내내기

C언어로 자바의 Class를 만들 수 있을까요? 완벽한 Class를 만들 수는 없지만 비슷하게 만들 수 있습니다. 기능적으로는 Class와 동일한 역할을 할 수 있지만 동적으로 할당/해제에는 제한이 있습니다.

 

C언어에서 typedef와 structure그리고 함수 포인터를 이용하면 class와 같은 기능을 할 수 있습니다.

왜 C언어로 Class를 만드는 다소 복잡하고 이해하기 쉽지 않은 구조를 만드냐고 물어보신다면, 우리가 앞으로 만들 디자인 패턴에서 반드시 사용되는 기법이기 때문입니다. 즉, 좀 더 효율적인 프로그램을 가능하게 합니다.

 

이번 예제는 다소 극단적인 C언어 Class입니다. 실제로 이렇게까지 사용하는 경우는 별로 없을 것 같습니다만 여러분들이 보시기에 알고 있거나 더 좋은 방법이 있다며 댓글을 남겨주세요.

 

일단 Class 원형이 필요합니다. 보통 Class에는 멤버변수(프로퍼티)와 멤버메소드가 필요합니다. 그리고 접근지정자(protect, private, public)가 있습니다만, C 언어에서는 접근 지정자를 구현할 방법이 없습니다.

 

멤버메소드의 원형을 typedef로 선언합니다.

typedef void (*ExecuteSumFunction)(void);
typedef void (*PutNumberFunction)(int number);
typedef void (*PrintSumFunction)(void);
 

그리고 Class원형을 구조체(structure)로 만듭니다.

typedef struct
{
  int sumResult;
  ExecuteSumFunction executeSum;
  PutNumberFunction putNumber;
  PrintSumFuntion printSum;
}Sum;
 

구조체 Sum은 Class의 원형입니다.

따라서 실제 선언은 다음과 같이 할 수 있습니다.

Sum simpleSum;
 

자바 같으면

Sum simpleSum = new Sum(); 
 

위와 같은 방식으로 했을 것입니다.

 

선언만 하면 소용이 없습니다. 함수 포인터에 주소를 지정해 줘야하며 멤버변수에는 초기화를 해줘야 합니다. 이것이 자바와의 결정적인 차이입니다. Java에서는 생성자에서 다 해주지만 C언어는 일일히 수작업으로 다 해줘야 합니다.

void SimpleSum(void)
{
   ... 
}

void SimplePutNumber(int number)
{
   ... 
}

void SimplePrintSum(void)
{
   ...
}
 

위와 같이 미리 메소드를 선언하고 다음과 같이 멤버변수 및 멤버메소드 하나씩 포인터를 지정해줍니다.

simpleSum.executeSum = SimpleSum;
simpleSum.putNumber  = SimplePutNumber;
simpleSum.printSum   = SimplePrintSum;
simpleSum.sumResult  = 0;
 

실제 실행은 다음과 같이 할 수 있습니다.

simpleSum.putNumber(10);
simpleSum.putNumber(20);
simpleSum.putNumber(30);
simpleSum.putNumber(40);
simpleSum.executeSum();
simpleSum.printSum();
 

Java처럼 쉽게 구현되지는 않지만 우리는 멤버변수와 멤버메소드를 가진 Class와 같은 패턴을 만들어 냈습니다. 물론 Java처럼 생산성이 높지는 않겠지만요.

 

오늘은 이만..