Reputation: 11921
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()
Upvotes: 0
Views: 901
Reputation: 37706
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.
Upvotes: 1