Require override of parent virtual function - c++

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?

Related

trouble understanding dynamic polymorphism

i'm new to c++, i'm learning dynamic polymorphism. But i'm getting really confused in the details. can anyone explain why we use virtual, override and use pure virtual functions even though we can just overload methods??
Thanks
Look at this code:
class Base
{
public:
void my_method() { std::cout << "base" << std::endl; }
};
class Derived : public Base
{
public:
void my_method() { std::cout << "derived" << std::endl; }
};
int main()
{
Base* object = new Derived;
object->my_method();
delete object;
return 0;
}
Implemented: http://www.cpp.sh/4z4p
The output of this is "base", despite object being constructed as Derived. Add a virtual in front of Base::my_method and this changes. Add an override to Derived::my_method and it won't compile should it not actually override.
Note that while here things are easy and clear, later on you have more complicated cases and you might think that you override while you actually don't. For example, you might change the signature of the method in the base class while forgetting to change it in the subclass, or the other way around.
Pure virtual methods are to show that something is to be implemented. The idea is that you create an interface which only determines what a set of classes is supposed being able to do but which does not do anything by itself. A pure virtual class, that is. In Java, interface is actually be a keyword on it's own.
If your base has a pure virtual method and your subclass does not implement it, your compiler will result in error, which is useful.
One thing not in your list but still somewhat useful is the keyword final with which you disallow deriving a class, essentially the opposite of an interface.
overloading functions means having the same function name with a different signature - i.e. different parameters and/or return type.
int test(int a)
void test();
here, int test(int a) is an overload of void test().
virtual only exists in the context of inheritance. it means "Hey, this function can be overriden in subclasses".
override is just a hint that you actually intend to override a virtual function.
pure virtual functions look like this:
void virtualFunction() = 0;
and means that this function is abstract (in C# and Java terms), i.e. it does not contain an implementation in this class, but is meant to be overriden in one of it's subclasses. Infact you cannot instantiate a class with a non-overriden pure virtual function.

C++, abstract class and inheritance

I'm trying to process classes instance two by two.
I have a abstract base class (IBase here) that contains a doStuff method.
This method will be overriden in extended class in order to process all other defined classes.
This is part of a library I'm building. I want Base objects to be written by the library user. Each Base class need to interact with another Base objects through the doStuff methode. The container is needed to handle multiples Base objects.
It is not the first time I run into this problem, but I can't remember how I did the last times. This kind of class can be used for a lot of thing. Here, it is a collision detection system. IBase represent an abstract HitBox and Container represente the Scene where collision occures. In this case, Container::process checks for transitions between hit boxes and Container::process is used to implement the optimizing algorithm (quadtree, ...).
I built those class in this way:
class IBase {
public:
virtual void doStuff(IBase* base) = 0;
}
class Base {
public:
virtual void doStuff(Base* base) {
foobar();
}
virtual void doStuff(IBase* base) {
// irrelevant
}
}
class Container {
public:
void process() {
for (std::list<IBase*>::iterator it=base_list.begin() ; it!=base_list.end() ; it++) {
for (std::list<IBase*>::itarator jt=std::next(it) ; jt!=base_list.end() ; jt++) {
(*it)->doStuff(*jt);
}
}
}
private:
std::list<Ibase*> base_list;
}
But in the loop, I can't reach void Base::doStuff(Base*) when working with two Base objects.
I can only call Base::doStuff(IBase*) which is not something I want.
Any help on this one ? I understand the problem, but I can't see a solution to it. Is this the good way to handle it or do I need to think again my architecture ? How would you do this ? I think a design pattern must exists for such a problem, but I didn't find any that fits.
Thanks
C++ does not support contravariance for arguments. See also Why is there no parameter contra-variance for overriding?.
You might be better off explicitly invoking doStuff(Base* base) from within the doStuff(IBase* base) body.
Your objects, when dereferenced from *it and *jt, are referenced as IBase objects, not Base objects. This means that only methods from IBase can be called.
Your virtual method:
virtual void doStuff(Base* base) { ... }
is not overriding anything. It is creating a new virtual method that is accessible from Base downward only. When you call doStuff from a IBase pointer, it's going to call:
virtual void doStuff(IBase* base) { ... }
which matches the signature defined in IBase.
If you want to execute your foobar function, you should do some kind of check on base when it's based into the overriding doStuff, cast it to Base* once you're sure it's safe, then work with it as needed.
virtual void doStuff(IBase* base) {
// not irrelevant
if (base->isBase())
{
foobar();
}
}
And finally, as previously suggested, make doStuff public.

Should interface/abstract class contains only pure virtual methods?

I am a bit weak with designing and I wonder whether it's a good design to have simple virtual methods (not only pure virtual) in an interface? I have a class that is some kind of interface:
class IModel {
void initialize(...);
void render(...);
int getVertexCount() const;
int getAnotherField() const;
};
the initialize and render methods need to be reimplemented for sure, so they are good candidates for pure virtual methods. However, the two last methods are very simple and practically always with the same implementation (just returning some field). Can I leave them as virtual methods with default implementation or is it better to have it pure virtual that needs to be reimplemented, because it's an interface?
We have to point out some differences:
there is no such thing as "some kind of Interface", is this class supposed to be an Interface or an Abstract Class?
If it's supposed to be an Interface then the answer is: all its methods must be pure virtual (no implementation) and it must not contain fields, not even one. The most you can (must, actually) do is, like jaunchopanza said, giving an empty body to the virtual destructor, thus allowing the derived classes to be destructed accordingly.
If, instead, it's supposed to be an Abstract Class then you're free to add the fields m_vertexCount and m_anotherField (I suppose) and implement getVertexCount() and ՝getAnotherField()՝ as you please. However, you should not name it IModel, because the I prefix should be used only for Interfaces.
Edit: I think I'm one of those "Believers" of which Bo Persson is talking about :)
You are facing a trade-off between code repetition and readability. The reader of your code will derive good help from every pure interface and from every non-overridden method. However, the default implementation wil be duplicated by every subclass. Whether or not you should provide a default implementation depends on the likelihood that the default implementation will change and will then need to be changed all over the place.
Without knowing these details, a hard yes-or-no answer cannot be given.
One thing you could do is make IModel be an interface and provide base class, eg ModelBase that implements common/repeating functionality.
class IModel
{
virtual void initialize(...) = 0;
virtual void render(...) = 0
virtual int getVertexCount() const = 0;
virtual int getAnotherField() const = 0;
};
class ModelBase : public IModel
{
// common functions
virtual int getVertexCount() const override { return vertexCount_; }
virtual int getAnotherField() const override { return anotherField_; }
protected:
int vertexCount_ = 0, anotherField_ = 0;
};
class MyModel : public ModelBase
{
virtual void initialize(...) override { ... }
virtual void render(...) override { ... }
};
The one downside of this approach is that there will be some (probably negligible) performance penalty due to extra virtual functions and loss of optimizations by the compiler.

Getting OOP right

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;
};

Appended '= x' after a method declaration in c++

In C++, when a method is declared, I've noticed that sometime the method may have an assignement appended to it.
Could anyone tell me what this is?
For example:
virtual void MyMethod () = 0;
What doe the '= 0' mean. :)
Thanks everyone !!!
It means it's a pure virtual function, i.e. no actual definition of it is available in this class and it must be overridden in a subclass. It's not actually an assignment as such, zero is the only value you can "assign".
And this is C++ syntax; in C# the same would be accomplished with the abstract keyword.
In C++ this means that the method is a pure virtual method.
This means that an instance of this particular class-type cannot be instantiated. You can only create instances of classes derived from this, which override all pure virtual methods in the base class.
A base class with pure virtual methods defines an interface that derived classes have to implement, and is not meant to be used on its own.
Contrary to what calmh claims, as far as I know pure virtual functions can be implemented and they can be called explicitly.
#include <cstdio>
class A
{
public:
virtual void foo() const = 0; //pure virtual
};
void A::foo() const { puts("A::foo"); }
class B: public A
{
public:
virtual void foo() const { puts("B::foo"); }
};
int main()
{
//A a; //this would be an error - main point of having pure virtual functions
B b;
b.foo();
b.A::foo();
}
Usually one wouldn't do this, though, except perhaps if the virtual destructor is pure in a base class (in this case it has to be defined).
In C#, that is a syntax error.
If you meant C++, see calmh's answer.