1

I have class

Class A{

};

typedef struct 
 {
  const char        *dec_text;
  void        (A::*TestFun)();

} Test ;

 Test _funs[] = {{"testLogOK", &A::testLogOK}, 
    {"testLoginException", &A::testLoginException}
};;

How can i initialize this Test Array in construct method. The _funs tracks the A's method name and corresponding address, the methods which like:

               void (methodName) (void)

In construction method, both below ways fail:

    _funs = {{"testLogOK", &A::testLogOK}, 
    {"testLoginException", &A::testLoginException}
};

The other question is how can i invoke the function pointer.. I tried the way like:

int
A::run (const char *name, int argc, ACE_TCHAR *argv[])
{
     for(int i=0; i< sizeof(_funs)/sizeof(Test); i++){
         Test test = _funs[i];
        *(test.testFun)();    //this->*(test.fun)();  Both fail with same error
                                //(this->*(test.fun))() works
        }
}     

The compile also fails with message:

 error C2064: term does not evaluate to a function taking 0 arguments

[UPdate]

I removed the struct Test and Test _funs out of Class A. But still have problem in A's method:

int   A::run (const char *name, int argc, ACE_TCHAR *argv[])

The testLogOK and testLoginException method do exist as member functions of class A

4
  • Pointer-to-member cannot use implicit this, you have to use the .* or ->* operator, like this->*(test.fun)(); Commented Mar 2, 2014 at 19:51
  • Which statements fail? Do the methods void A::testLogOK() and void A::testLoginException() exist? They're not shown here. Commented Mar 2, 2014 at 19:51
  • thanks @BenVoigt, the this->*(test.fun)() still the same error... Commented Mar 2, 2014 at 20:13
  • @shijiexu: Oops, need more parentheses: (this->*(test.fun))(); Commented Mar 2, 2014 at 20:18

1 Answer 1

2

Try this:

class A
{
public:
    struct Test
    {
        const char        *dec_text;
        void        (A::*TestFun)();
    };
    A(Test tt[])
    {
        for (int i=0; tt[i].dec_text; i++)
            _funs[i] = tt[i];
    }
    void f1() { printf("this is f1\n"); }
    void f2() { printf("this is f2\n"); }
    void f3() { printf("this is f3\n"); }

    Test _funs[100];
};

A::Test tt[] = 
{
    { "Function f1", &A::f1},
    { "Function f2", &A::f2},
    { "Function f3", &A::f3},
    {0, 0}
};

void test()
{
    A a(tt);
    (a.*(a._funs[0].TestFun))();

    A *pa = new A(tt);
    (pa->*(pa->_funs[1].TestFun))();
    delete pa;

    // EDIT: call f3 
    (a.*(tt[2].TestFun))(); // this will call directly from the global table
}

This will invoke the function assigned to the pointer. This can be improved quite a bit if you typedef the pointer to the member

typedef void (A::*PF_T)();

and use a std::map as container:

std::map<std::string, PF_T> func_map;

It can be streamlined a lot more, but I hope it helps up to this point.

Sign up to request clarification or add additional context in comments.

6 Comments

This doesn't show how to initialize the array. However, the invocation is correct and the suggestion of std::map is good, so +1
Thanks @DNT.. I removed struct Test and declared Test _funs as global. In that case, how to invoke the function inside of void A::test() method?
Ok, Ben Voigt is right, so I edited my answer and added an initialization approach. The code now if run, will print "this is f1" and next line: "this is f2". You dont need to declare it global shijie xu, but since your member functions will not change, you can have member _funs just point to the global array if you want. My approach copies the global array elements to _funs elements. This may give you more flexibility in replacing some functions with others at runtime.
That still isn't initializing the member, it's assigning it.
PS @shijiexu If you want to have a single array with member functions and no copies, you can declare _funs as static and change my 'tt' to A::_funs in the initialization part. Then you will not need to pass anything to the constructor and you can remove the for loop from it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.