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 ?
Related
So, if I have
class base
{
public:
virtual void start();
virtual void stop();
void doSomething() { start(); .... stop(); }
}
class derived : public base
{
public:
void start();
void stop();
}
calling derived.doSomething() will call derived::start() and derived::stop().
BUT this only works if they're virtual.
I wanted to know why it doesn't work without the virtual keyword, meaning the lower level details. I can't find much about this online...
Thanks!
Without the virtual keyword, base::doSomething code has NO IDEA about the derived version's of those methods (think linker resolution)
If a function is declared virtual, all overrides of this function are stored in a virtual member function table (vtable). When such a function is called in your code, the program really just points to the location of the table. The table is then used to determine the correct function to call at runtime.
If a function is not declared virtual, start() and stop() in the base class implementation of doSomething are always just pointing to the base class definition of these functions.
C++ lets you chose between both mechanisms, because the runtime look-up in the vtable results in some overhead, which C++ generally does not force on the user - "you only pay for what you use".
The examples and invocation sections of the wiki article show the technical side pretty well.
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.
If I have the following override of a virtual event:
void derivedClass::method(event)
{
// my stuff
baseClass::method(event); // <--
}
what does the // <--- line does? What does it call? I don't think it calls the base class' method because it's virtual (so no body)
As you are suggesting, it calls the base class' method. The fact that it is virtual it only means it can be overridden and still access to the derived class' method from a pointer/reference to the base class.
The reason to do that can be easily seen with an example:
class Base {
public:
virtual void foo() {
/* do some generic stuff */
}
};
class Derived : public Base {
public:
void foo() {
/* do some specific stuff */
/* if you also want to do the generic stuff,
you can call the same method from the base class. */
Base::foo();
}
}
It might be the case that you do not want to do the generic stuff for Derived class. Then you would just remove the call to Base::foo().
Here you have a good reference on virtual methods.
It does call the base class method. Yes, the derived method is being called "polymorphically", but it can call its base method using Base::method
When qualified name (<class name>::<method name>) is used in a class method call, the method is called directly, non-virtually. In your example, baseClass::method is called. Since qualified name is used, the fact that the method is virtual means absolutely nothing and makes no difference whatsoever.
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.
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.