C / C++,  Programming

[C/C++] Non-static Member Function Pointer in Class

C 또는 C++를 사용하다 보면 function pointer를 다루는 경우가 간혹 생긴다.

Non-class Function Pointer

#include <iostream>
#define FUNC_NUM 3
using namespace std;
 
typedef void(*voidFuncP) (void);
 
voidFuncP *funcList;
 
void func1 (void)
{
    cout << "func1" << endl;
}
 
void func2 (void)
{
    cout << "func2" << endl;
}
 
void func3 (void)
{
    cout << "func3" << endl;
}
 
int main (void)
{
    funcList = new voidFuncP[FUNC_NUM];
    funcList[0] = func1;
    funcList[1] = func2;
    funcList[2] = func3;
 
    for (int i=0; i<FUNC_NUM; i++) {
        funcList[i]();
    }   
    return 0;
}
func1
func2
func3

위 코드는 class 또는 struct를 사용하지 않는 프로그램에서 사용 가능하다. 그러나 class의 member function으로 사용하는 경우는 위 프로그램으로 사용하지 못한다.

Class Member Function with Static

#include <iostream>
#include <vector>
 
#define FUNC_NUM 3
using namespace std;

class A
{   
    typedef void(*voidFuncP) (void);
    
public:
    A() {
        count = 0;
        funcArray = new voidFuncP[FUNC_NUM];
    
        funcArray[0] = &func1;
        funcArray[1] = &func2;
        funcArray[2] = &func3;
    }
    
    static void func1 (void)
    {
        cout << "func1" << endl;
    //    count++;
    }
    
    static void func2 (void)
    {
        cout << "func2" << endl;
    //    count++;
    }
    
    static void func3 (void)
    {
        cout << "func3" << endl;
    //    count++;
    }
 
    void addFunc (void)
    {
        funcVector.push_back(&func1);
        funcVector.push_back(&func2);
        funcVector.push_back(&func3);
    }
 
    void runFunc (void)
    {
        for (int i=0; i<FUNC_NUM; i++)
            funcArray[i]();
        for (int i=0; i<FUNC_NUM; i++)
            funcVector[i]();
    }
 
private:
    vector<voidFuncP> funcVector;
    voidFuncP *funcArray;
    int count;
};
 
int main (void)
{
    A<int> a;
    a.addFunc();
    a.runFunc();
 
    return 0;
}
 func1
 func2
 func3
 func1
 func2
 func3

위 코드는 class 내에서 member function의 pointer를 사용하는 예시 코드다. Class의 instance의 function의 pointer는 dynamic memory region (stack)에 저장되기 때문에 static 매크로를 통해 해당 함수의 주소를 고정시켜서 사용해야 된다. 그러나 이런 경우 class 내 member variable 또는 member function을 호출이 안된다는 문제가 존재한다.

따라서 위에 보면 member function(func1, func2, func3)에서 member variable인 count를 접근하게 되면 build error가 발생한다.

Non-static Member Function Pointer in Class

#include <iostream>
#include <vector>
     
#define FUNC_NUM 3
using namespace std;
     
class A
{    
typedef void(A::*voidFuncP) (int _arg);
public:
    A() {
        count = 0;
        funcArray = new voidFuncP[FUNC_NUM];
     
        funcArray[0] = &A::func1;
        funcArray[1] = &A::func2;
        funcArray[2] = &A::func3;
     
        funcVector.push_back(&A::func1);
        funcVector.push_back(&A::func2);
        funcVector.push_back(&A::func3);
    }
     
    void func1 (int _arg)
    {
        cout << "func1: " << _arg << endl;
        count++;
    }
     
    void func2 (int _arg)
    {
        cout << "func2: " << _arg << endl;
        count++;
    }
     
    void func3 (int _arg)
    {
        cout << "func3: " << _arg << endl;
        count++;
    }
     
    void callMemberFunc (A *pInst, void (A::*pFunc)(int a), int _arg)
    {
        (pInst->*pFunc)(_arg);
    }
     
public:
    void selfCallMemFunc (void)
    {
        for (int i=0; i<FUNC_NUM; i++) {
            callMemberFunc(this, funcArray[i], i*100);
        }
     
        for (auto iter=funcVector.begin(); iter!=funcVector.end(); iter++) {
            callMemberFunc(this, *iter, 100);
        }
    }
     
private:
    int count;
    voidFuncP *funcArray;
    vector<voidFuncP> funcVector;
};   

int main ()
{    
    A a;
    a.selfCallMemFunc();
     
    return 0;
}
 func1: 0
 func2: 100
 func3: 200
 func1: 100
 func2: 100
 func3: 100

위 코드는 앞서 언급한 두 문제를 해결할 수 있는 프로그램으로, array와 vector를 모두 사용한 예제다. 추가로 함수의 argument를 함께 전달할 수 있도록 했다.

Leave a Reply

Your email address will not be published. Required fields are marked *