non-static member functions


The code below use a VxWorks API (taskSpawn) to call member functions.  For taskSpawn to work in a C++ world the solution is to call a static member function with taskspawn and pass as  one of your 10 arguments the "this" pointer.   Then in the static member function, call the
regular/NON-static member function using the conventionally passed "this" pointer.  Trouble is I'd like to make TaskMain generic such that I could call obj->StartB() and obj->StartC().
How could I achieve this?  In the interim I'm reviewing 'callbacks' and things which i'm not sure if this in an ideal fit.  Code samples as always appreaciated.

class FOO
{
public:
  Foo();
  static int TaskMain(Foo*obj)
  {
    obj->StartA();   // would like to make this generic so it's starts B and C
  }

  void StartA(void);
  void StartB(void);
  void StartC(void);
};


Foo::Foo()
{
    t_id = taskSpawn( "TaskMain", 90, 0, 10000,
              (FUNCPTR)TaskMain,this,0,0,0,0,0,0,0,0,0 );
/*
    t_id = taskSpawn( "TaskMain", 90, 0, 10000,
              (FUNCPTR)TaskMain,this,0,0,0,0,0,0,0,0,0 );

    t_id = taskSpawn( "TaskMain", 90, 0, 10000,
              (FUNCPTR)TaskMain,this,0,0,0,0,0,0,0,0,0 );
*/
}

FOO::StartA()
{
  printf ( " Task A started \n");
}

FOO::StartB()
{
  printf ( " Task B started \n");
}

FOO::StartC()
{
  printf ( " Task C started \n");
}

A few approaches I've pondered
------------------
Approach 1
------------------
Pass an additional variable (in addition the 'this' pointer) that I could 'switch' on inside TaskMain.  For instance

    t_id = taskSpawn( "TaskMain", 90, 0, 10000,
              (FUNCPTR)TaskMain,this,10,0,0,0,0,0,0,0,0 );   // pass bogus 10
    t_id = taskSpawn( "TaskMain", 90, 0, 10000,
              (FUNCPTR)TaskMain,this,20,0,0,0,0,0,0,0,0 );  // pass bogus 20
:
:
then inside
  static int TaskMain(Foo*obj, int idx)
  {
    switch (idx)
    {
       case 10:
          obj->StartA();  
       case 20:
          obj->StartB();  
       case 30:  // not shown above
          obj->StartC();  
  }

This seems 'inelegant'.

------------------
Approach 2
------------------
Pass the name of the functions, except here i'm stuck on how to implement a switch statement inside TaskMain  but this wont work since taskSpawn wants a static member function.  I'd be willing to give this a try except I'm not sure how to implement the switch on a functoin name inside TaskMain.


Thanks in advance for the assistance.
forums_mpAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
You could pass a pointer to the member function you want to start, e.g.

typdef void (Foo::*STARTFN)();

 static int TaskMain(Foo*obj, STARTFN p)
  {
    (obj->p*());   // would like to make this generic so it's starts B and C
 }

and call it like

TaskMain ( theObj, Foo::StartB);
efnCommented:
Approach 1 is not so bad.  You could make it a bit more palatable by using an enumeration or named constants instead of magic numbers.

jkr has told you how to do Approach 2.

Another possibility is to use multiple FOO objects.  Tell each FOO which start function it is supposed to run and have it store that in a member variable.  Then pass a different object address in each TaskSpawn call.  If all the tasks need a common FOO to share data, you can make two separate classes, one, say FOO, for the common data, the other, say FOOstarter to decide what to start.  Each FOOstarter could have a member variable that points to the common FOO, so they all can use it.  Taking that a step further, instead of one FOOstarter class that you have to tell what to run, you could have separate FOOStartA, FOOStartB, and FOOStartC classes.  This design may or may not be preferable to the others, depending on the details of your application.

--efn
forums_mpAuthor Commented:

efn could you elaborate on the possiblity of multiple FOO objects with sample code.  I think I'm followign what you're getting at but there's a degree of uncertainty.   Would like to keep in my back pocket.

In the interim, I'll try jkr's approach but  I'm confused about something here.

Should
    (obj->p*());   // would like to make this generic so it's starts B and C

be written as

    (obj->(*p)());   // would like to make this generic so it's starts B and C
Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

jkrCommented:
Ooops, you are right - that was a typo :o)

It indeed should read  (obj->(*p)());
forums_mpAuthor Commented:

Wrote a test program in an attempt to try to implement approach 2.  The intent is to call StartA, StartB, StartC inside the constructor (current implementation) or perphaps inside main.

 (obj->(*p)()); generates errors and I'm sort of mystified - even with my book open


#include <iostream>

class TEST
{
private:
      int spawned;
      static int bogus;    // how would i initialize bogus

public:
      typedef void (TEST::*FUNCPTR)();

      TEST() : spawned(0)
      {  
            std::cout <<  " Constructor called " << std::endl;
            TEST::TaskMain(this, StartA);
            // TEST::TaskMain(this, StartB);
            // TEST::TaskMain(this, StartC);
      }
      ~TEST() { std::cout <<  " Destructor called " << std::endl; }

      static int TaskMain(TEST* obj, FUNCPTR p)
      {
            // (obj->(*p)());   //errors
            return 0;
      }
      void StartA() { std::cout <<  " A Started " << std::endl; }
      void StartB() { std::cout <<  " B Started " << std::endl; }
      void StartC() { std::cout <<  " C Started " << std::endl; }
};


#include "test_main.h"

int main ()
{
      TEST *ptr = new TEST;
      delete ptr;
}

One other thing.   Just wanting to ensure I'm reading right.  There's no way to initialize a static member variable except outside of the class?
What's the point of making static private?

efnCommented:
Here's a multiple-FOO example based on the last code you posted.

class TEST
{
private:
      int spawned;
      static int bogus;    // how would i initialize bogus
      
public:
      typedef void (TEST::*TESTPTR)();

      TESTPTR pFunc;

      TEST(TESTPTR func) : spawned(0), pFunc(func)
      {  
            std::cout <<  " Constructor called " << std::endl;
            TEST::TaskMain(this);
      }
      ~TEST() { std::cout <<  " Destructor called " << std::endl; }
      
      static int TaskMain(TEST* obj)
      {
            (obj->*(obj->pFunc))();
            return 0;
      }
      void StartA() { std::cout <<  " A Started " << std::endl; }
      void StartB() { std::cout <<  " B Started " << std::endl; }
      void StartC() { std::cout <<  " C Started " << std::endl; }
};

int main ()
{
      TEST *ptrA = new TEST(TEST::StartA);
      TEST *ptrB = new TEST(TEST::StartB);
      TEST *ptrC = new TEST(TEST::StartC);
      delete ptrA;
      delete ptrB;
      delete ptrC;
      system("pause");
      return 0;
}

This is the first approach I mentioned. The second one would be more complicated.

I think your call to a member function using a pointer should be:

            (obj->*p)();

> There's no way to initialize a static member variable except outside of the class?

I believe you're supposed to be able to initialize it in the class declaration, but some compilers (like VC++ 6) don't let you.

> What's the point of making static private?

The same as the point of making anything else private:  to keep functions outside the class from seeing or changing it.

--efn

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.