0

I'm having trouble getting member function pointers to work (I don't know whether what I'm trying to do is possible). I want to set a member variable (which is a pointer to a non-static function in another class) and then call that function. I then want to be able to set it to another member function in a different derived class and call that. The 2 derived classes are created by templates, as per below. Can I achieve this and if so, what am I doing wrong?

// Forward declare these, their implementation is irrelevant to the question 
class A;
class B;

// declare a base class that contains a function log() that we want to call
class BaseClass {
   public:
      BaseClass() {}
      virtual ~BaseClass() {}

      virtual void log() {}  // want to call this via function pointers
};

//Using a template means we don't have to specify the type in the vector  
template<class T>
class TemplateVectorOfBaseClass : public BaseClass {
   protected:
      std::vector<T> peripherals;      
}

//  this specific implementation does stuff using Class A
template <int randomTemplateParameter>
class DerivedTemplateClassThatDoesStuffWithAs : public BaseClass
    public:
       DerivedTemplateClassThatDoesStuffWithAs() : TemplateVectorOfBaseClass<A>() {}
       void log() {do_something_here_involving_As();}
       int i[randomTemplateParameter];
};

//  this specific implementation does stuff using Class B
template <int randomTemplateParameter>
class DerivedTemplateClassThatDoesStuffWithBs : public BaseClass
    public:
       DerivedTemplateClassThatDoesStuffWithBs() : TemplateVectorOfBaseClass<B>() {}
       void log() {do_something_here_involving_Bs();}
       float f[randomTemplateParameter];  
};

// Class that contains both templates as member variables    
class ContainerClass {
   public:
      ContainerClass();

      DerivedTemplateClassThatDoesStuffWithAs dtca<5>;
      DerivedTemplateClassThatDoesStuffWithBs dtcb<10>;

      void (BaseClass::*log)();  // pointer to member function log()
    }

// usage
ContainerClass cc;

cc.container.log = &dtca.log;
cc.*log(); // should call vectorContainingAs.log()

cc.container.log = &dtcb.log;
cc.*log(); // should call vectorContainingBs.log()
6
  • 2
    class ContainerClass { public: ContainerClass container;. How could this ever compile? Commented Jul 14, 2014 at 18:22
  • Your example is still a little unclear. cc.*log() doesn't make sense. You intend to run the function pointed at by "cc.log" against the "cc" object? Or did you intend it to run against the dtca object? Commented Jul 14, 2014 at 18:22
  • You can't use pointers to non-static functions. Commented Jul 14, 2014 at 18:23
  • 2
    @dari Of course you can. Your code contains lots of errors irrelevant to the specified problem, you should correct them before pasting it. Commented Jul 14, 2014 at 18:24
  • @Holt oh yeah, thx. Thinking before posting helps. Commented Jul 14, 2014 at 18:26

1 Answer 1

1

I can't really rely on your code because it's full of mistakes, so here it's how it should work with a simplified version:

class A { } ;
class B { } ;    

class BaseClass {
public:
    virtual void log () {
        std::cout << "Log BaseClass." << std::endl ;
    }
};

template <class T>
class TVector : public BaseClass { } ;

template <int N>
class DTCA : public TVector <A> { 
public:
    virtual void log () { 
        std::cout << "Log DTCA." << std::endl ;
    }
} ;

template <int N>
class DTCB : public TVector <B> { 
public:
    virtual void log () {
        std::cout << "Log DTCB." << std::endl ;
    }
} ;

class Container {
public:
    DTCA <5> dtca ;
    DTDB <10> dtcb ;
    void (BaseClass::*log) () ;
} ;

I assume the mistakes in the previous part was due to bad copy/paste. The part where you were mainly wrong was the way of assigning the method to the pointer, and the way to call the method on an object:

int main () {
    Container cc ;
    cc.log = &BaseClass::log ; // Store the log member function into cc.log

    (cc.dtca.*cc.log) () ; // Call it on dtca
    (cc.dtcb.*cc.log) () ; // Call it on dtcb

    return 0 ;
}

Output:

Log DTCA.

Log DTCB.

You can not take the address of a method from an instance, you will get something like:

ISO C++ forbids taking the address of a bound member function to form a pointer to member function.

So you take the address to the method, since the type of your variable is (BaseClass::*)() you need to take it directly from the BaseClass. Then, you need to call it using an instance of BaseClass or a derived class.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.