∇ 프로그래밍 소품 및 팁

 ▼ Protected 멤버 함수를 파라미터로

C++

N/A

Protected를 멤버 함수를 파라미터로 넘기려면 크게 두 가지가 필요하다. 첫째는 protected에 대한 권한이 없을 때 접근하는 방법에 대한 것이고 또 하나는 멤버 함수를 파라미터로 넘겨서 실행하는 방법에 대한 것이다.

첫 번째에 대한 이야기는 이전 팁에서 언급된 것이기 때문에 생략하고 두 번째에 대한 것만 이야기 하겠다. 일반적으로 C에서 함수를 파라미터로 넘기기 위해서는

    void Print(void (*fnPrint)(const char*))

와 같은 방법으로 선언하면 되었다. 그런데 class의 멤버 함수의 경우에는 조금 다른 문법을 사용해야 하는데, CA라는 class 멤버 함수를 파라미터로 받는 다음 다음과 같이 된다..

    void Print(void (CA::*fnPrint)(const char*))

앞 쪽에 CA라는 class를 의미하는 namespace 표시를 추가하는 방법으로 해결되는 것이다. 이렇게 해서 class 멤버 함수를 파라미터로 보낼 수가 있지만 이렇게 받은 파라미터를 직접 실행하지는 못한다. 위와 같은 선언이라면 단순한 파라미터일뿐이지 실행 가능한 함수 형태라고는 볼 수 없기 때문이다. (하지만 C 형태의 함수 파라미터는 실행까지 가능하다) 그 이유는 class 멤버 함수는 암묵적으로 this를 포함하여야 하기 때문에 스스로 실행은 불가능 한 것이다. 그렇다면 결국 this가 되는 class 인스턴스도 넘겨 주어야 하기 때문에 다음과 같은 형태가 되어야 한다.

    void Print(CA* pThis, void (CA::*fnPrint)(const char*))

이로서 this와 class 멤버 변수가 모두 전달 되었다. 하지만 하나의 난관이 더 남아 있다. 이 2개의 파라미터를 어떻게 조합하느냐는 것이 문제이다. 그 방법도 C의 경우를 조금 응용해 보면 결론이 나오는데 다음과 같이 하면 된다.

    (pThis->*fnPrint)("first parameter");

이 전체를 테스트 하기 위해서 다음의 test case를 만들어 보았다.

    01: #include <iostream>
    02:
    03: class CA
    04: {
    05:     int m_data;
    06:
    07: protected:
    08:     void _Print(const char* szText)
    09:     {
    10:         std::cout << szText << "(" << m_data << ")" << std::endl;
    11:     }
    12: public:
    13:     CA(int data): m_data(data) {};
    14: };
    15:
    16: /////////////////////////////////////////////////////////
    17: // 파라미터로 받은 this와 멤버 함수를 조합한다
    18: void PrintProxy(CA* pThis, void (CA::*_Print)(const char*),
                        const char* szText)
    19: {
    20:     (pThis->*_Print)(szText);
    21: };
    22:
    23: /////////////////////////////////////////////////////////
    24: // 파라미터로 받은 this의 protected 멤버 함수를 파라미터로 넘긴다.
    25: void PrintProxy(CA* pThis, const char* szText)
    26: {
    27:     class CB: public CA
    28:     {
    29:     public:
    30:         CB(int data): CA(data) {};
    31:         void Print(const char* szText)
    32:         {
    33:             PrintProxy(this, &CB::_Print, szText);
    34:         }
    35:     };
    36:
    37:     static_cast<CB*>(pThis)->Print(szText);
    38: }
    39:
    40: /////////////////////////////////////////////////////////
    41: // TEST CASE
    42: int main(void)
    43: {
    44:     CA a(100);
    45:
    46:     // a의 protected 함수인 _Print()를 이용해 문자를 출력
    47:     PrintProxy(&a, "my message");
    48:
    49:     return 0;
    50: }