일반적인 클래스로는 c-style의 콜백을 처리할 수 없다는 것을 알았고, 이는 단순한 대처로는해결하기 힘듬을 알았다. 그렇다면 어떻게 클래스를 사용하면서도, c-style을 유지할 수 있을까?
한 가지 방법으로는 static 변수를 멤버 변수로 사용하는 방법이다. 그러나 이 방법은 그리 유용하지 못하다. 왜냐하면 static 멤버 변수는 클래스를 선언하지 않고도 사용 가능하며, 그 클래스가 모두 공유하는 변수이기 때문에, 사실상 전역 변수이나 다름이 없어지기 때문이다.
우리는 클래스의 멤버 변수가 코드 안에서 자유롭게 선언되기를 (정확하게는 스택/힙 영역에서 메모리 확보가 이루어지기를) 원한다. 한가지 기본적인 대안은, 콜백 함수 내에서 자신이 속한 클래스의 레퍼런스를 가지고 있다가 콜백 함수에서 사용하는 것이다. 이 방법은 나름 설득력이 있어 보인다.
#include <iostream> // 전역변수 콜백 함수 포인터. // 어떤 라이브러리 어딘가에 있다고 가정한다. void (*g_callback)(void) = NULL; // 우리는 C-Style의 함수가 아닌 class를 필요로 한다. class cb_class { public: cb_class() : n(100) {} ~cb_class() {} // 라이브러리는 이 함수를 필요로 한다. // static 키워드를 포함할 때와 그렇지 않을 때를 비교하라. static void callback(void) { cb_class& real = *ptr; std::cout << "Our callback function is called.n"; std::cout << "member variable n: " << real.n << std::endl; } static cb_class* ptr; private: int n; }; cb_class* cb_class::ptr = NULL; int main(int argc, char** argv) { // 라이브러리에 우리의 콜백 함수를 등록하는 과정이라고 가정한다. g_callback = &cb_class::callback; // 일반적인 콜백 클래스를 선언한다. cb_class cb; cb_class::ptr = &cb; // g_callback이 우리가 만든 callback을 대신한다. // 현재 우리가 만든 main 함수 안에서 호출되고 있으나 // 이 while문의 구조는 라이브러리 내부 어딘가라고 가정한다. int nCount = 3; // 3회 callback 함수를 호출 while(nCount--) { g_callback(); } return EXIT_SUCCESS; }
가장 단순한 형태이지만, 이것은 콜백을 수행하는 스태틱 함수에서 멤버 변수를 사용할 수 있는 방법이 될 수 있다. 그러나 콜백함수의 인자를 넣고 참조하는 방법의 가독성은 좋지 않을 뿐더러, 콜백 함수에서 클래스의 멤버에 아무 제한 없이 접근할 수 있다는 점은 문제로 남아 있다. 이러한 문제는 콜백 클래스와 데이터 클래스를 분리함으로써 해결할 수 있다.