I need to pass an object's static method as callback function using following code:
glutDisplayFunc(callback)
Where callback is a static method of some class - baseClass::callback(). It compiles fine. But now I want to have a derived class (having baseClass as it's parent) having the same callback function - that is, I want to overwrite the callback function.
I've overwritten it in derivedClass but derivedClass::callback() is not getting called.
PS. I'm calling glutDisplayFunc(callback) withing the base class. Code looks like:
baseClass::someFunction(){
glutDisplayFunc(callback);
}
How do I pass derivedClass::callback instead of baseClass::callback withing a method of baseClass? All methods are static.
C++ does not support virtual static methods, so you can't do what you're trying to do directly. What you should be able to do is create a non-static virtual method that returns a function pointer, and override that in your derived class to return a pointer to it's static callback method.
i.e. something like this:
class A
{
public:
typedef void(*CallbackFunction)(void);
public:
static void callback(void)
{
std::cout << "A::callback" << std::endl;
}
virtual CallbackFunction getCallback()
{
return callback;
}
void someFunction()
{
glutDisplayFunc(getCallback());
}
};
class B: public A
{
public:
static void callback(void)
{
std::cout << "B::callback" << std::endl;
}
CallbackFunction getCallback()
{
return callback;
}
};
Not exactly ideal, but it's a decent workaround for C callbacks that don't support context parameters.
The short answer is that you can't, and furthermore you generally don't want to. A base class generally shouldn't have direct knowledge of specific derived functions.
The usual pattern for this is to have a static function in the base class that invokes a virtual function, then override the virtual function in the derived class. I'm not sure if that applies here though -- to work, you need to be able to get a parameter passed to the callback function. The parameter you pass is a pointer to the object, so you cast that back to the base object type, then invoke the correct virtual function off of that pointer.
In the specific case of glutDisplayFunc, however, I don't believe that's possible -- it doesn't allow you to get a parameter passed to the callback function. I'm afraid there is no real cure other than to switch to something other than GLUT if you want to do this style of programming.
Related
Here are my code
#include <iostream>
using namespace std;
class BaseClass
{
public:
BaseClass() {}
void init(const int object) { cout<<"BaseClass::init"<<endl; }
void run(const int object) { cout<<"BaseClass::run calls =>"; init(object); }
};
class Derived : public BaseClass {
public:
Derived() {}
void init(const int object) { cout<<"Derived::init"<<endl; }
};
int main() {
BaseClass b;
b.init('c');
b.run('c');
Derived d;
d.init(5); // Calls Derived::init
d.run(5); // Calls Base::init. **I expected it to call Derived::init**
}
And here is generated output
BaseClass::init
BaseClass::run calls =>BaseClass::init
Derived::init
BaseClass::run calls =>BaseClass::init
With call d.run(5), Why "BaseClass::init" is being called instead of "Derived::init" ?
I though we need virtual functions only when calling through a pointer.
What is the rationale behind keeping such behavior ?
Why "BaseClass::init" is being called instead of "Derived::init" ?
Because init is a non-virtual member function. To have the desired effect, you need to make init a virtual member function as shown below:
class BaseClass
{
public:
BaseClass() {}
//NOTE THE VIRTUAL KEYWORD HERE
virtual void init(const int object) { cout<<"BaseClass::init"<<endl; }
//other member function here as before
};
Demo
I though we need virtual functions only when calling through a pointer.
Note that the statement init(object); is equivalent to writing
this->init(object); //here `this` is a pointer
When you wrote:
d.run(5);
In the above statement, first the address of object d is implicitly passed as the first argument to the implicit this parameter of member function run. The type of this implicit this parameter is BaseClass* and this happens due to derived to base conversion. Now, the call init(object); is equivalent to this->init(object);. But since init is a non-virtual member function, the call is resolved at compile time meaning the base class init will be called.
Basically when a member function is called with a derived class object, the compiler first looks to see if that member exists in the derived class. If not, it begins walking up the inheritance chain and checking whether the member has been defined in any of the parent classes. It uses the first one it finds. This means for the call d.run(5) the search for a member function named run starts inside the derived class. But since there is no function named run inside derived class, the compiler looks into the direct base class BaseClass and finds the member function named run. So it stops its search and uses this found run member function. And as i said, in your example, init is non-virtual and so the call is resolved at compile time to the base class run.
On the other hand, if we make init to be a virtual member function, then this call will be resolved at run-time meaning the derived class init will be called.
I though we need virtual functions only when calling through a pointer.
No. Thats not right. You need to make a function virtual when you want to enable calling it based on the dynamic type of the object. And once you do have a virtual function you can use pointers or references to make use of the virtual dispatch.
You need to make a method virtual when you want to override it. As BaseClass::run is not overridden by Derived::run, there is no virtual dispatch and calling init from BaseClass::run calls BaseClass::init. If you want to enable virtual dispatch for BaseClass::init you need to declare it virtual.
Further, consider that your code is equivalent to:
void run(const int object) {
cout<<"BaseClass::run calls =>";
this->init(object);
}
this is BaseClass*, hence BaseClass::init is called. You are calling init via a pointer, but that does not matter because init is not virtual. If you want to call init based on the dynamic type of the object, thats exactly what virtual is good for. The "overhead" you refer to in comments is not really overhead, but just the minimum needed to get the behavior you want. If you can change the design and do not need runtime polymorphism you can take a look at CRTP wich is a form of static polymorphism.
I recently finished a bit of a program that I was hoping would work the way I expected it to, and as it turns out, it did! Here is the situation:
I have a Handler class which is the base class:
class Handler
{
public:
Handler();
virtual ~Handler();
virtual void handle(SOCKET socket);
protected:
virtual void doWork(SOCKET socket);
private:
std::thread * handlerThread;
static void processData(SOCKET socket);
};
I have a PrintHandler which is a subclass of Handler:
class PrintHandler : public Handler
{
public:
PrintHandler();
~PrintHandler();
protected:
virtual void doWork(SOCKET socket);
};
Here are the definitions of doWork in the base class Handler and the subclass PrintHandler:
void Handler::doWork(SOCKET socket)
{
std::cerr << "If you see this, you didn't override the doWork function" << std::endl;
}
void PrintHandler::doWork(SOCKET socket)
{
std::cerr << "This is in the base class" << std::endl;
}
When I create a pointer to a PrintHandler and cast it to a pointer to a Handler and call the handle method on that object via method pointer:
void Handler::handle(SOCKET socket)
{
handlerThread = new std::thread(&Handler::doWork, this, socket);
}
the doWorkexecutes as the subclass method that overrode the base class method. When I override a method in the manner that I did, does it replace the base class method in memory? Is there anyway to call the original base class doWork method? Does calling it with a method pointer change which method gets called?
In this thread it gives you a means to do it from the sub class. How would I call the original base class method from the base class and what does the actual structure of the object look like in memory?
I understand this is probably a lot to answer, so if you could maybe provide your knowledge on the questions in the first paragraph and suggest some reading for the questions in the second, I think that would be most appropriate.
Thank you!
When I override a method in the manner that I did, does it replace the base class method in memory?
No, both functions still exist. Overriding affects which version is chosen when called on a particular object; the base version is still needed for objects of that type, or other derived classes that don't override it.
Is there anyway to call the original base class doWork method?
Yes, you can call it non-virtually:
Handler::doWork();
Does calling it with a method pointer change which method gets called?
No, virtual dispatch chooses the same override whether you call the function directly, or via a pointer-to-member-funcion. It only depends on the dynamic type of the object it's called on.
what does the actual structure of the object look like in memory?
That's up to the implementation. Typically, the object contains a pointer (known as a vptr or virtual pointer) to some class-specific metadata, which contains a table of pointers to the virtual functions (known as a vtable). When you (virtually) call a virtual function, it looks in that table to find which function to call. A pointer to a virtual function will specify which table entry to use, rather than which function to call, so that virtual dispatch still works on any type that overrides that function.
when you do
std::thread(&Handler::doWork, this, socket);
You ask to call this->doWork(socket) virtually.
You may create an other method which call not virtually your virtual method. as:
void Handler::callHandlerDoWork(SOCKET socket)
{
Handler::doWork(socket); /* no virtual call */
}
void Handler::handle(SOCKET socket)
{
handlerThread = new std::thread(&Handler::callHandlerDoWork, this, socket);
}
Note: Do you really need that Handler::handle is virtual ?
How and when would I call a super class method? Please referr to code segment for the two options:
class SuperClass {
public:
void method();
};
class SubClass : public SuperClass {
public:
void someOtherMethdo(){
this->method();
SuperClass::method();
}
};
using this->method() you call a function that is either implemented in your superclass, either by your own class.
When using superClass::method(), you make sure to call the one implemented by your parent.
#include <iostream>
#include <string>
class A {
public:
void func() {
std::cout << "A func" << std::endl;
}
};
class B : A {
public:
void func() {
std::cout << "B func" << std::endl;
}
void exec() {
this->func();
A::func();
}
};
int main() {
B b;
b.exec();
return 0;
}
This sample code will output
B func
A func
this->method();
...calls method on the derived class (and is the same as writing simply method();). This could call the inherited method from the parent (and does in the example), or it could call an overridden version in the child class (and will, if one exists).
SuperClass::method();
...will always call the method on the parent. This syntax is often used within an override in the child, when you want to keep and extend the functionality of the parent class method. E.g.
Class SubClass: public SuperClass {
//...
void method() {
SuperClass::method();
//...
}
};
Note that if you use the first syntax in this second case, you'll get recursion.
Note also that this has nothing to do with virtual methods. Marking a method as virtual means that, when the method is called via a base class pointer, the most-derived class method available will be called. In the code above, it makes no difference whether any of the methods are virtual since there are no base class pointers involved.
this->method
Will default to the local implementation in your derived class first, if that one isn't present, it will take the superclass method. If that one is not present it will give a compilation error.
superClass::method()
Will always direct to the method in your superclass
In most cases you want this->method. superClass::method() Is usefull when part of a method is implemented in the superclass and you want to extend it in the derived class. something like:
Class SubClass : public SuperClass {
public:
void someOtherMethdo(){
SuperClass::someOtherMethdo();
//Rest of the method
}
}
this->method() leaves room for ambiguity under certain circumstances (e.g. if more than one ancestor defines method with this signature), but at the same time allows method to be called no matter where exactly it is defined. If method is virtual it will call the most-derived version.
SuperClass::method() is explicit. It will either call that specific method or give a compiler error.
In this particular example, no difference.
If the method is virtual:
this->method() will call the function dynamically (call the top-most implemented version of the class)
SuperClass::method() results in a static call.
this->method(); call parent's in your case or if it's virtual - call the top of implemented functions in vtable. SuperClass::method(); will call parent's method.
I have a function like this:
void something(void *obj)
{
obj->Set();
}
The compiler says that left of the dereference operator has to be a pointer to a class/struct/union/generic (translated from german not sure about wording).
The idea is that I want to call the something function of obj no matter what is passed to something. It is ensured that it has this function. How can i achieve that?
--EDIT--
I started to work on an existing Software which has like > 100 Classes for datatypes. In one part of the code there is a big switch statement which depending on an id creates an instance of one of these classes and calls the Set function for that one. Now i want to do multiple of these calls parallel, and because of this i want to bring the ->Set() call to a seperate function which i then can call in a new thread. Sadly there is no baseclass and i cant change too much in the "big picture". What is the best way to do this?
C++ doesn’t allow this (for good reasons: even if you can ensure that the object always has a function, C++ cannot, and since you can make mistakes, C++ is justified in distrusting you).
The proper way to do this is to have a common base class which defined this method for all types that you want to use here, and then use this common base class as the argument of this function.
Alternatively, if it’s known at compile time which type is used here, then the appropriate implementation uses templates:
template <typename T>
void f(T const& obj) {
obj.something();
}
Whatever you do, void* is not appropriate. There are very rare legitimate use-cases for it in C++.
You need a base class or interface for whatever is passed into doSth:
class Base
{
public:
virtual void something() = 0; //override this in derived classes
}
doSth(Base* obj)
{
obj->something();
}
You can also cast the void* back to the original type:
doSth(void* obj)
{
((Base*)obj)->something();
}
but passing a void* as parameter suggests a faulty design. What exactly are you trying to achieve?
You need to implement pure virtual Base class with this function:
class Base
{
public:
virtual ~Base(){}
virtual void somefunction()=0;
}
class Derived1: public Base
{
public:
void somefunction()
{
//do something
}
}
class Derived2: public Base
{
public:
void somefunction()
{
//do something
}
}
And than use dynmic cast to get Base* from void*
doSth(void *obj)
{
Base *bobj=dynamic_cast<Base*>(obj);
if ( bobj )
bobj->somefunction();
}
Or mor simplier:
doSth(Base *obj)
{
obj->somefunction();
}
And usage is like:
Base *p1 = new Derived1();
Base *p2 = new Derived2();
doSth(p1); // cals somefunction in Derived1 class
doSth(p2); // cals somefunction in Derived2 class
The doSth method could take a function pointer as a parameter.
doSth( (*someFunc)() ) {
obj->*someFunc();
}
The call would look like:
doSth( &function );
When passing function pointers between different classes you should create a typedef for each function pointer and use qualifiers for each function identifier.
Just define an interface that lists all the functions of all the objects that you want to reference by the pointer, but the type of this pointer should not be void, but the name of this interface instead.
Then you will be able to call every function of every object that you want by this pointer, but make sure that all structures and classes of the objects implement all the functions of the interface!
This is also important to write the : public and then the name of the interface in the header of every structure and class!
I have a base class MessageHandler and 2 derived classes, MessageHandler_CB and MessageHandler_DQ.
The derived classes redefine the handleMessage(...) method. MH_DQ processes a message and puts the result in a deque while MH_CB processes the message and then executes a callback function.
The base class has a static callback function that I pass along with a this pointer to a library which calls the static callback when a new message is available for processing.
My problem comes when I am in the static callback with a void * pointing to either a MH_DQ or a MH_CB. If I cast it to the base class the empty MessageHandler::handleMessage(...) method is called, rather than the version in the appropriate derived class.
What is the best way to address this situation from a design perspective and/or what language features might help me to implement a solution to my problem?
Thanks in advance!
Okay, the virtual method did not work like magic. There is a twist to the story. I have a static method in the base class and a pure virtual member function to handle the message processing, but I want to first call a member function in the pure virtual base class to preprocess the message before I route it to the derived class.
So I have :
class MH {
...
static int CallBackFunction(MessageData *md, void *this_ptr) {
((MH *)this_ptr)->preprocess(md);
return 1;
}
virtual int preprocess(MessageData *md) {
// do some stuff
. . .
handleMessage(md);
return 1;
}
virtual void handleMessage(MessageData *) = 0;
};
class MH_CB : public MH {
...
void handleMessage(MessageData *md) {
// do something
...
}
};
class MH_DQ : public MH {
...
void handleMessage(MessageData *md) {
// do something different
...
}
};
Unfortunately, this code produces a run-time error that a pure virtual function is being called. Any thoughts?
TIA
Make the original method call virtual.
Don't pass a void* in the callback - pass a pointer to the base class, and declare handleMessage to be virtual.
Add the virtual keyword to the declaration/definition of the method in the base class.
In fact if the method in the base class is never supposed to run then you can specify that it's pure virtual to declare it with no body at all, instead of defining an empty body:
class MessageHandler
{
public:
virtual void handleMessage(...) = 0;
};
Mark the handleMessage() as virtual by prefixing void handleMessage() or whatever declaration in the base class with the word virtual. Then, make sure that the derived classes implement the exact same message signature (i.e. same return type and parameter types).
Also- instead of a void* use a MessageHandlerBase* (or whatever is appropriate). Then you don't need to cast. Casting is often the sign of a logic error on the part of the programmer.