0

I have the following call:

void Derived::GetEntry(Skill&);
InorderTraverse(GetEntry);

Which calls

void Base<ItemType>::InorderTraverse(void Visit(ItemType&)) const

Attempting to compile as written generates

error C3867: 'Derived::GetEntry': function call missing argument list; use '&Derived::GetEntry' to create a pointer to member

Using &Derived::GetEntry generates

cannot convert parameter 1 from 'void (__thiscall Derived::* )(Skill &)' to 'void (__cdecl *)(ItemType &)'

Changing the declaration to static void GetEntry... fixes these problems, but creates a new set of problems (namely that I can't access non-static objects (nonstatic member reference must be relative to a specific object)

I have a similar traversal operation that works fine with a static declaration, since the called function just displays information about each object on which it is called.

I've been searching for a few days now for an answer, and I feel like it's something simple. Is there a way to use a nonstatic function as a parameter in another function call?

The complete code is: https://github.com/mindaika/SkillTree

Randall Sewell
  • 43
  • 1
  • 10
  • Duplicate of http://stackoverflow.com/questions/400257/how-can-i-pass-a-class-member-function-as-a-callback – Zac Howland Aug 22 '13 at 15:29
  • 1
    Not seeing the actual code makes it somewhat problematic in comprehending this question (at least for me). The first snippet isn't even valid C++ code, as the first line is a *declaration*, and the second is an actual function invocation. What is the *actual* problem? Are you attempting to pass a pointer-to-member function to another function to be used for an enumeration algorithm? The linked question from Zac covers this nicely. – WhozCraig Aug 22 '13 at 15:29
  • if you know exactly which functions you will pass, and these functions are accessible from the context where you wish them to be called, you could replace that function passing by an enum, and make a switch at call site. That's not as flexible though, of course. – didierc Aug 22 '13 at 15:34
  • I'm not sure how the question Zac linked is a duplicate since the solution to that was "use a static function," which is what I'm trying to avoid. @WhozCraig Yes, the first line is a C++ declaration, indicating the function is declared non-static. The second line is a function invocation. The actual problem is that the function invocation InorderTraverse(GetEntry) can't be performed using the derived class function GetEntry as an argument. I'm not using an enumeration algorithm; I'm traversing a BST to retrieve an entry from the tree. I'm not sure what other code to post to clarify. – Randall Sewell Aug 22 '13 at 18:26
  • For what its worth, traversing a BST *is* an enumeration algorithm if there ever was one. Regardless, so the function you wish to pass *is* or is *not* a member function? A static would be simple enough, but it sounds like you want to pass a derived *member*, and if so, its still doable, but a bit more wiring involved. – WhozCraig Aug 22 '13 at 18:33
  • @WhozCraig Ah, well I did not know that, but I do now. Yes, what I'm trying to do is pass a derived member to a base member (from the derived class). Ultimately, there's two things I need to do with the tree: traverse through and print out information for each node (which works fine with the static Display function), and traverse through it to find a specific object and return that object. – Randall Sewell Aug 22 '13 at 18:56

2 Answers2

3

Edit: Inserted full working example instead.

I suggest you use the std function pointers instead.

For instance:

#include <functional>
void main()
{
class TheClass
{
public:

   TheClass()
   {
       m_function = ( std::tr1::bind(&TheClass::run, this) );
   };

   void run()
   {
          // stuff to do
   };

   std::tr1::function<void ()> m_function;
};

TheClass theclass;
theclass.m_function();

}

m_function (); // call function

MasterPlanMan
  • 992
  • 7
  • 14
  • Or, just use C++11 instead of appending `::tr1` everytime or boost if C++03 is a must. +1 anyways. –  Aug 22 '13 at 15:32
  • @Adam I tried the example you provided, modified for my code, but it doesn't seem to work. However, reading through some of the other comments, it looks like ::bind is ultimately the solution, and I just need to understand how to use it properly. Thank you! – Randall Sewell Aug 22 '13 at 18:30
0

As I mentioned in my question, I was trying to get around the "memory leak" caused by using a static variable (it's not actually a leak, since statics are destroyed, but not until after the leak detector runs). I ended up using a modification of the encapsulated pointer described here: C++ freeing static variables

Community
  • 1
  • 1
Randall Sewell
  • 43
  • 1
  • 10