Solved

non-static member functions

Posted on 2003-11-10
6
2,092 Views
Last Modified: 2008-02-01

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.
0
Comment
Question by:forums_mp
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
  • 2
6 Comments
 
LVL 86

Assisted Solution

by:jkr
jkr earned 100 total points
ID: 9716883
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);
0
 
LVL 15

Expert Comment

by:efn
ID: 9716993
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
0
 

Author Comment

by:forums_mp
ID: 9717283

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
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 86

Expert Comment

by:jkr
ID: 9717302
Ooops, you are right - that was a typo :o)

It indeed should read  (obj->(*p)());
0
 

Author Comment

by:forums_mp
ID: 9718133

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?

0
 
LVL 15

Accepted Solution

by:
efn earned 150 total points
ID: 9718854
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
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

717 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question