Solved

non-static member functions

Posted on 2003-11-10
6
2,082 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
  • 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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
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

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

708 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now