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.
Related
So, based on a cursory search, I already know that calling a virtual function (pure or otherwise) from a constructor is a no go. I have restructured my code to ensure that I am not doing that. While this causes the user of my classes to add an extra function call in their code, this is really not that big of a deal. Namely, instead of calling the constructor in a loop, they now call the function which (in fact!) increases performance of the code since we don't have the housekeeping of building and destroying the object in question every time.
However, I have stumbled across something interesting...
In the abstract class I have something like this:
// in AbstractClass.h:
class AbstractClass {
public:
AbstractClass() {}
virtual int Func(); //user can override
protected:
// Func broken up, derived class must define these
virtual int Step1() = 0;
virtual int Step2() = 0;
virtual int Step3() = 0;
// in AbstractClass.cpp:
int AbstractClass::Func() {
Step1();
// Error checking goes here
Step2();
// More error checking...
// etc...
}
Basically, there is a common structure that the pure virtual functions follow most of the time, but if they don't Func() is virtual and allows the derived class to specify the order. However, each step must be implemented in derived classes.
I just wanted to be sure that there's nothing that I necessarily am doing wrong here since the Func() function calls the pure virtual ones. That is, using the base class, if you call StepX(), bad things will happen. However, the class is utilized by creating a derived object and then calling Func() (e.g. MyDerivedObject.Func();) on that derived object, which should have all the pure virtual functions overloaded properly.
Is there anything that I'm missing or doing incorrectly by following this method? Thanks for the help!
Func is calling the virtual ones, not the pure virtual ones. You would have to qualify the calls with a scope operator, i.e. AbstractClass::Step1() to call THAT (virtual pure) function. Since you are not, you will always get an implementation by a derived class.
A virtual function in a base class makes the derived classes able to override it. But it seems things stop there.
But if the base class virtual function is pure, that forces the derived classes to implement the function.
As a side comment you can make the Step1, Step2, Step3 methods private so that you'll be prevented by the compiler from directly calling them.
I'm working on a serialization system, and all my serializable classes implement
virtual void serialize(Buffer buffer);
When a pointer is going to be serialized, I need to call the serialize() function of the class itself, and not that of any of its parents, even if the pointer is a parent type, and I've been running into a lot of bugs because I don't notice that a child class doesn't even have serialize() at all so the parent serialize() class is just being called
ie
class A
{
virtual void serialize();
}
class B:public A
{
virtual void serialize();
}
class C:public B
{
virtual void serialize();
}
void doSerialization(A *a)
{
a->serialize();
}
C *c=new C();
doSerialization(c);
right now, if C didn't have a serialize function, B::serialize() would be silently called. I'd prefer an error message, or anything else that will at least point it out to me. Is there any keyword in C++ (even '11) that would do this?
There's no easy way of doing so in C++.
There is a hack though, explained in this answer, using virtual inheritance and forcing your classes to register which serialize method they are using.
Use pure virtual function in parent:
virtual void serialize(Buffer buffer) = 0;
At compile time you can only do that by making the function a pure virtual function in classes that are not final:
class A
{
virtual void serialize() = 0;
}
class B:public A
{
virtual void serialize() = 0;
}
class C final:public B
{
virtual void serialize();
}
Of course that means that all concrete classes in your design need to be final. If you must inherit from concrete classes, you can't enforce this at compile time.
right now, if C didn't have a serialize function B::serialize() would be silently called.
No, you'll get linker error. As I see, that's what you want.
One variant to solve this is is to not inherit several layers, so instead of class C: public B, you use class C: public A. Of course, that's not necessarily a suggestion for all scenarios.
At some point sooner or later, you do have to leave things in the hand of the programmer.
There may be some ways to check this as well, - maybe create a temporary pointer to B and check if typeid(*this) == typeid(temp) or some such?
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.
Ok, this is my problem. I have the following classes:
class Job {
bool isComplete() {}
void setComplete() {}
//other functions
};
class SongJob: public Job {
vector<Job> v;
string getArtist() {}
void setArtist() {}
void addTrack() {}
string getTrack() {}
// other functions
};
// This were already implemeted
Now I want to implement a VideoJob and derived it from Job. But here is my problem. I also have the following function witch it was set to work only with SongJob:
void process(SongJob s)
{
// not the real functions
s.setArtist();
..............
s.getArtist();
.............
s.getArtist();
...............
s.setArtist()
}
Here I just want it to show that the function uses only derived object methods. So if I have another object derived from Job, I will need to change the parameter to Job, but then the compiler would not know about thoose functions and I dont what to test for everyone what kind of object it is and then cast it so I can call the correct function.
So it is okay to put all the functions in the base class, because then I will have no problem, but I don't know if this is correct OOP, if one class deals with Songs and the other with videos, I thing good oop means to have 2 clases.
If I didn't make myself clear, please say so and I will try explaining better.
And in short words, I want to use polymorfism.
It is totally fine to put all the things that the classes SongJob and VideoJob have in common into a common base-class. However, this will cause problems once you want to add a subclass of Job that has nothing to do with artists.
There are some things to note about the code you have posted. First, your class Job is apparently not an abstract base class. This means that you can have jobs that are just jobs. Not SongJob and not VideoJob. If you want to make it clear that there can not be a simple Job, make the base-class abstract:
class Job {
virtual bool isComplete() = 0;
virtual void setComplete() = 0;
//other functions
};
Now, you cannot create instances of Job:
Job job; // compiler-error
std::vector<Job> jobs; // compiler-error
Note that the functions are now virtual, which means that subclasses can override them. The = 0 and the end means that subclasses have to provide an implementation of these functions (they are pure virtual member functions).
Secondly, your class SongJob has a member std::vector<Job>. This is almost certainly not what you want. If you add a SongJob to this vector, it will become a normal Job. This effect is called slicing. To prevent it, you'd have to make it a std::vector<Job*>.
There is much more to say here, but that would go to far. I suggest you get a good book.
In your Base class Job you could add those methods as virtual methods so that a class deriving from Job may or may not override these specific methods.
In your SongJob class you override the methods and dont override them in VideoJob
In, void process() pass a pointer to Base class Job
void process(Job *s)
It will then call the appropriate methods depending on the adress of the objec s is pointing to which will be a SongJob object.
In C++, you have to do two things to get polymorphism to work:
Access polymorphic functions by a reference (&) or pointer (*) to a base type
Define the polymorphic functions as virtual in the base type
So, change these from:
class Job {
bool isComplete() {}
void setComplete() {}
};
void process(SongJob s)
{
// ...
}
To:
class Job {
public: // You forgot this...
virtual bool isComplete() { }
virtual void setComplete() { }
};
void process(Job& s)
{
// ...
}
If you can't define all the functionality you need inside process on your base class (if all the member functions you'd want don't apply to all the derived types), then you need to turn process into a member function on Job, and make it virtual:
class Job {
public:
virtual bool isComplete() { }
virtual void setComplete() { }
virtual void process() = 0;
};
// ...
int main(int argc, char* argv[])
{
SongJob sj;
Job& jobByRef = sj;
Job* jobByPointer = new SongJob();
// These call the derived implementation of process, on SongJob
jobByRef.process();
jobByPointer->process();
delete jobByPointer;
jobByPointer = new VideoJob();
// This calls the derived implementation of process, on VideoJob
jobByPointer->process();
return 0;
}
And of course, you'll have two different implementations of process. One for each class type.
People will tell you all sorts of "is-a" vs "has-a" stuff, and all sorts of complicated things about this silly "polymorphism" thing; and they're correct.
But this is basically the point of polymorphism, in a utilitarian sense: It is so you don't have to go around checking what type each class it before calling functions on it. You can just call functions on a base type, and the right derived implementation will get called in the end.
BTW, in C++, virtual ... someFunc(...) = 0; means that the type that function is defined in cannot be instantiated, and must be implemented in a derived class. It is called a "pure virtual" function, and the class it is defined on becomes "abstract".
Your problem comes from the fact you're calling a process method on an object. You should have a method Process on the Job class and override this method in your derived classes.
use pure virtual functions:
class Job
{
virtual string getArtist() =0;
};