The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

array of func pointers in C++ class

How can I declare an array of function pointers as a class member and initialize it at the same time?

class XYZ
{

void (*funcs[2])() = { &func1, &func2 };

};

This doesn't work.. I can't make funcs static either and I don't really want to declare funcs in the header file and fill it elsewhere..
coder
Sunday, April 15, 2007
 
 
BTW, func1 and func2 are members of class XYZ
coder
Sunday, April 15, 2007
 
 
In C++ you *declare* data in the H file and *define* data in the CPP file.
Christopher Wells Send private email
Sunday, April 15, 2007
 
 
You cannot.  The closest you can come is to create a constructor

XYZ::XYZ () {
 funcs[0] = &func1;
 funcs[1] = &func2;
}

There is a gross hack you could do with templates, and maybe one with verdiac constructors.  But neither is a great solution.

Sunday, April 15, 2007
 
 
Like any other class member, initialize it in the constructor.
clcr
Sunday, April 15, 2007
 
 
I wonder what the OP is trying to do with function pointers in a C++ class that wouldn't be better done with virtual methods and subclasses, or maybe functors.

It looks like they want to be able to use an array index to select one of two behaviors, but that the behaviors themselves (not which one is active when) are entirely determined at compile time. For only two behaviors, the array is clearly overkill and a simple conditional statement would suffice. For much more than two behaviors, however, the array would still be nice.

This could be achieved with functors, obects that encapsulate the method to be called, one sub-class for each distinct behavior. Then an array of functors would be build in the constructor and you could call the common method name on the functor in the indexed array slot. The functor in this case could be pretty simple, consisting of nothing more than the common method declaration.

  class Functor {
      virtual int func() = 0;
  };

  class Functor1: Functor {
      int func(...);
  };

  Functor1::func(){...}

  class Functor2: Functor {
      int func();
  };

  Functor2::func(){...}

  ...

  class Something {
      Functor *fnarr[N];
      Something(){
        fnarr[0] = new Functor1;
        fnarr[1] = new Functor2;
        ...
      };
      int doit(int i);
  }

  Something::doit(int i){
      return fnarr[i].func();
  }

You STILL have to build your array of functors in the constructor, but at least you are using the method dispatcher for it's intended purpose (actual method selection uses VTables based on the object you index in the array) instead of rolling your own.
Jeff Dutky Send private email
Sunday, April 15, 2007
 
 
Jeff, thank you. That looks good to me.
coder
Sunday, April 15, 2007
 
 
Sounds like what you want is an array of pointers to member functions. Have a read here to learn more about those:

http://www.goingware.com/tips/member-pointers.html

As has been mentioned, you can't initialize an array at the point where it's defined. But you can fake it with an inline function, either the constructor or something called by the constructor:

class XYZ 
{
public:
    XYZ()
    {
        funcs[0] = func1;
        funcs[1] = func2;
    }
    void DoSomething(int i);
private:
    void func1();
    void func2();
    typedef void (XYZ::*funcptr)();
    funcptr funcs[2];
};

void XYZ::DoSomething(int i)
{
    (this->*funcs[i])();
}
Mark Ransom Send private email
Monday, April 16, 2007
 
 
Damn, wish I would have read this thread about two weeks ago. The functor idea is a lot better than the silliness that I came up with for mod_auth_sqlite3.  I'm thinking that it's going to get reimplemented in a couple of weeks.
Clay Dowling Send private email
Monday, April 16, 2007
 
 
to Clay Dowling: if you're going to use functors, my implementation is not the best (at least, it's not the most C++-ish). Have a look at

http://www.newty.de/fpt/functor.html

and

http://www.sgi.com/tech/stl/functors.html

for good discussions of functors in C++. The main difference is that these functors, rather than provide some named virtual method, overload the () operator. I'm not sure I really like this better than a named method, but it appears to be the standard way to implement a functor in C++.
Jeff Dutky Send private email
Monday, April 16, 2007
 
 
There is no benefit to using these functors over the method pointer method.  It adds code without providing any benefits.

Monday, April 16, 2007
 
 
Yeah, functors are cool, but I don't think they add anything in this case. And they don't give you access to the internals of the class, unless you make them friends and pass a pointer to the object.
Mark Ransom Send private email
Monday, April 16, 2007
 
 
You can define an array in .h and initialize it in .Cpp:

class XYZ
{
typedef void (XYZ::*MyFuncPtrType)(void);
protected:
    static MyFuncPtrType _funcEntries[];

protected:
    void Func1(void) { }
    void Func2(void) { }
};

XYZ::MyFuncPtrType XYZ::_funcEntries[] = { &XYZ::Func1, &XYZ::Func2 };
Glitch
Monday, April 16, 2007
 
 
Jeff:
The benefit of using the operator() instead of some other method, is that the STL and many of the algorithms in the std C++ library can take a thing that can be invoked for every item in a sequence.  Invoking means using the operator() call.  This works for function pointers if you pass one, as well as anything that defines the operator() function.

Often a functor will be a simple class that just has the  operator() call, but sometimes it is useful to create a functor with parameters passed to the functor's constructor, to store some internal state that the functor uses to modify it's behaviour or pass parameters to the operation you want.

In addition, making your functor class inherit from the unary_function or binary_funtion classes is very useful if you want to be able to use other adapters from the std library with your functors.  See Effective STL for some very good examples and further information.
Stephen Depooter
Wednesday, April 18, 2007
 
 

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
 
Powered by FogBugz