Alternatives to abstract base class for storage - c++

I'm wondering about the available alternatives to run-time polymorphism, specifically, an alternative to having a common base class between my classes in order to store and interact with instances of derived classes.
RTP has disadvantages of indirection through vtable look-up, and also forces the derived classes to be stored as pointers, and so generally they must be dynamically allocated. From what I've been told, this hinders inlining and compiler optimisations.
In short, I don't want this:
class Animal
{
public:
virtual void noise() const = 0;
};
class Dog : public Animal
{
public:
virtual void noise() override const {std::cout<<"Woof!\n";};
};
class Cat : public Animal
{
public:
virtual void noise() override const {std::cout<<"Meow!\n";};
};
//...
std::vector<Animal*> animals;
I want something like this:
class Dog
{
public:
void noise() const {std::cout<<"Woof!\n";};
};
class Cat
{
public:
void noise() const {std::cout<<"Meow!\n";};
};
//...
std::vector<*Things that have noise()*> animals;

In your example, I can not help you, but for classes with data members, here is an optimization.
Let's suppose we want to create a bullet-hell game.
In a naive approach, we need a class Bullet :
class Bullet {
public:
void draw(Renderer& r);
virtual void update_logic(float delta);
void run_physics();
protected:
float vx, vy; //velocity
private:
float x, y; //position
//...
};
So, the update_logic method would be called to set the velocity of the bullet, then run_physics will apply this velocity to the position.
Modifying logic needs polymorphism, so your collection becomes std::vector<Bullet*> (or std::vector<std::unique_ptr<Bullet> > in modern c++).
Then, in your main loop, first you update the logic, then the physics, then you draw your bullets.
Of course it is inefficient because of pointer dereference and vtables etc.
What you can do instead is :
class Bullet {
public:
void draw(Renderer& r);
void update_logic(float delta) { logic->update(delta); };
void run_physics();
void setVelocity(float, float);
void setLogic(BulletLogic*);
private:
float x, y, vx, vy;
BulletLogic* logic;
};
So now, you can use std::vector<Bullet>, and the indirection will occure only when updating logic, but neither while running phyics or drawing the bullet.

Related

C++ vector of classes which implement multiple virtual classes?

I'm looking to have an vector of class instances which implement multiple virtual classes.
e.g.
// assume that all the classes here have implementations
class A
{
public:
virtual void doThing();
};
class ImplementsA
: public A
{
public:
void doThing() override;
};
class B
{
public:
virtual void doSomethingElse();
};
class ImplementsB
: public B
{
public:
void doSomethingElse() override;
};
class AB
: public A
, public B
{
public:
void doThing() override;
void doSomethingElse() override;
};
class OtherAB
: public A
, public B
{
public:
void doThing() override;
void doSomethingElse() override;
// these implementations are different than in AB
};
int main()
{
// here I'd like to have a vector of classes AB and OtherAB, and any other classes which implement both A and B
}
I've been poking around but I haven't found any information about how to do this. Is this possible in C++? If so, how would the vector be structured/initialized to allow it?
Thank you!
You need the Adapter and/or the Proxy and/or the Decorator design pattern. Try to wrap all the inheritance in ABwrapper : public A, public B
and create a vector of ABwrapper
class ABWrapper: public A, public B
{
public:
A *a; B *b; AB *ab;
void doThing()
{
if (this->ab==nullptr) {this->a->doThing(); return;}
this->ab->doThing();
}
void doOtherThing()
{
if (this->ab==nullptr) {this->b->doOtherThing(); return;}
this->ab->doOtherThing();
}
}
...
Vector<ABWrapper>
There are various ways to go about it:
Create a bundling interface, and manage your objects using pointers to them.
This runs counter to the interface-segregation-principle, and pre-supposes that you can modify all the affected classes.
Still, if you can do it and accept the drawback, it's the most efficient choice.
Save a pointer to each interesting interface.
If you need at most two interfaces, this is the second most efficient choice. Space use obviously increases linearly.
Write your own wrapper abstracting the differences away. See smart-pointer and std::function for ideas.
Use std::any and a map for registering how to access the interface. If few statically known fully derived types are involved, static functions might serve, and std::variant is enough.

Visitor pattern and constness

I am running into a problem concerning the visitor pattern and constness.
Assume a visitor pattern implementation in C++ for a small game in which you draw stuff on the screen (depending on the internal state of the drawable objects) and at the same time run a logic that can change their internal state (pretty much any game you can imagine). Please, forgive any errors in code as this is done on the fly.
//Forward declaration of classes and visitor...
//class Game_actor; This one will be abstract, virtual, whatever.
class Game_actor_item;
class Game_actor_player;
class Game_actor_invisible;
class Visitor
{
public:
// virtual void visit(Game_actor& r)=0;
virtual void visit(Game_actor_player& r)=0;
virtual void visit(Game_actor_item& r)=0;
virtual void visit(Game_actor_invisible& r)=0;
};
Then, some interface-like basics:
//This one defines stuff that can be on the screen.
class Drawable
{
public:
virtual void draw(Screen&)=0;
};
//This one defines stuff that changes its state. Let's assume that do_logic
//returns an integer that means something to the controller and can be
//interpreted via a long list of "message_codes" (1=Add score, 2=Substract
//score, 3=Something else...). Each actor will run its logic and return its
//message, that will be stored and interpreted later. This is mostly crap,
//I know, but makes for a quick example.
class Game_actor
{
private:
float x;
float y;
public:
virtual int do_logic()=0;
void accept_visitor(Visitor& v)=0;
};
Next, our object hierarchy: Items and the player are derived from the actor, that defines part of their internal state. They can, of course, be drawn to the screen. There's a particular actor that won't be drawn, because it is invisible and controls something else.
class Game_actor_item: public Drawable, public Game_actor
{
//Lines and lines of code.
virtual void draw(Screen& s) {/* [...] */}
virtual int do_logic() {/* [...] */}
};
class Game_actor_player: public Drawable, public Game_actor
{
//Lines and lines of code.
virtual void draw(Screen& s) {/* [...] */}
virtual int do_logic() {/* [...] */}
};
class Game_actor_invisible: public Game_actor
{
//Lines and lines of code.
virtual int do_logic() {/* [...] */}
};
Finally, visitor specialization. We're gonna define two visitors, one is going to collect all drawable actors and other is going to dispatch messages to the game controller. Drawable actors will be collected from
a vector of its base class
class Visitor_drawing:public Visitor
{
private:
std::vector<Drawable *> draw_all_these;
public:
// virtual void visit(Game_actor& r)
virtual void visit(Game_actor_player& r) {draw_all_these.push_back(&r);}
virtual void visit(Game_actor_item& r) {draw_all_these.push_back(&r);}
//This one won't be drawn.
virtual void visit(Game_actor_invisible&) {}
std::vector<Drawable *> get_me_the_drawables() {return draw_all_these;}
}
class Visitor_logic:public Visitor
{
private:
std::vector<int> messages;
public:
// virtual void visit(Game_actor& r)
virtual void visit(Game_actor_player& r) {messages.push_back(r.do_logic());}
virtual void visit(Game_actor_item& r) {messages.push_back(r.do_logic());}
virtual void visit(Game_actor_invisible&) {messages.push_back(r.do_logic());}
std::vector<int> fetch_me_the_messages() {return messages;}
}
So, that's our setup. It is missing the "accept_visitor" methods, but I'm sure you get the idea here. Every final branch of the hierarchy just does void accept_visitor(Visitor& v) {v.visit(*this);}.
At any given time in our loop we collect drawable things and run logic:
std::vector<Game_actor*> actors;
while(loop)
{
Visitor_drawing dw;
Visitor_logic dl;
for(Game_actor * g : actors)
{
dw.visit(g);
dl.visit(g);
}
std::vector<Drawable *> draw_these=dw.get_me_the_drawables();
std::vector<int> messages=dl.fetch_me_the_messages();
for(Drawable * d : draw_these) d->draw(screen);
for(int * m : messages) interpret_message(m);
};
And here's my problem: I really want to keep my objects const where they should be. One requisite for this is that drawing them is never going to change their internal state (save a mutable int times_drawn, for example) so they could (and should (??)) be const. Doing their logic may change their state at each given turn (for example, moving them around the screen).
Given this particular setup, how would you manage having a const and non const visitor?. I have tried splitting the base visitor into const and non const base classes so they do
class Const_visitor
{
virtual void visit(const Thing&)=0;
};
class Non_const_visitor
{
virtual void visit(Thing&)=0;
};
class Visitor_drawing:public Const_visitor
{
virtual void visit(const Thing&)=0;
};
class Visitor_logic:public Non_const_visitor
{
virtual void visit(Thing&)=0;
};
But it seems that I would have to implement separate "accept_visitor" methods as the compiler doesn't distinguish between calls:
void accept_visitor_const(Const_visitor& v)=0;
void accept_visitor(Non_const_visitor& v)=0;
This leads to all kinds of duplication in the base visitor classes (basically writing everything twice, const and non const versions) and then separating the calls in the main loop: there's no single accept_visitor anymore and you have to know in advance what kind of visitor are you expecting (the side effect is that it really reads "I will accept this visitor that promises not to change my internals", which is somewhat desirable).
Anyway, Am I missing any other option that does not radically change this setup?. Is this a suitable and desirable option?
As always, many thanks in advance.

C++: disallowing virtual function in derived class at compile vs runtime

I have a parent class RO that has a method void setup(const int* p). I need a child class RW to have same method that allows non-const pointers only.
I do it by creating two methods in class RO and disallowing one of them in class RW:
class RO
{
public:
void setup(int* p) { DO SMTH }
virtual void setup (const int* p) { RO::setup( const_cast<int*>(p) ); }
// the rest...
void read() const;
};
class RW : public RO
{
public:
virtual void setup (const int* p) { throw SMTH }
// the rest...
void write();
};
I'd like to be able to disallow RW::setup at compile time when possible. I.e.,
const int* p;
RO* ro = new RW;
ro->setup(p); // Throw at run time, since it can be unknown
// at compile time that ro points to RW and not to RO.
RW* rw = new RW;
rw->f(p); // Disallow this at compile time, since it is
// known at compile time that rw points to RW.
Is there a way to do it?
Use private instead of public inheritance. Make methods of the parent class available in the child class using the using keyword.
Public inheritance is meant for situations where someone who uses a parent class object might as well use a chid class object (look up Liskov substitution principle for details). Your requirement breaks that, so it's no case for public inheritance.
It sounds like class RO has an invariant: "Never modifies *p" (even though it does a sneaky const_cast on p). If class RW violates that invariant, it CANNOT be a subclass of class RO.
I'm guessing what you really want is something more like:
class Readable {
public:
virtual ~Readable();
virtual void read() const = 0;
};
class RO
: public Readable {
public:
void setup(const int* p);
void read() const;
private:
const int* m_p;
};
class RW
: public Readable
{
public:
void setup(int* p);
void read() const;
void write();
private:
int* m_p;
};
And if the followup question is: "What about DRY? Now I have to implement read() twice?", note that you can define a static member function in base class Readable something like:
static void do_read(const int* p);

Inheritance c++ Child Parent

I have simple problem:
class Weapon{
public:
int dmg;
float speed;
int rate;
};
class Uzi : public Weapon{
public:
Uzi();
void Shot(float angle);
};
Class Pistol : public Weapon{
public:
Pistol();
void Shot(float angle);
};
Later in code when I reserve for example:
Weapon wep;
wep = Uzi;
wep.Shot(15);
It doesn't work:
undefined reference to `Weapon::Shot(float)'
Can I reserve different type of 'wep' variable?
I think no because weapons are changing(pistol/uzi/...).
Thanks in advance!
Weapon wep;
wep = Uzi;
This is slicing. Uzi is-a Weapon, but not the other way around. You can use pointers for this:
Weapon* wep = new Uzi();
Also, you get the error because there is no Shot() method in the Weapon() class.
You might want to declare it virtual and also make it abstract (optional). You make it virtual to allow polymorphism.
That way:
Weapon* wep = new Uzi();
wep->Shot();
will call Shot() in the Uzi class, although it's called on a Weapon pointer.
The following should work:
class Weapon{
public:
int dmg;
float speed;
int rate;
virtual void Shot(float angle) {}; //move implementation to cpp file
};
You forgot to declare void Shot(float angle) in the Weapon class.
For polymorphism, you need to virtualise the method, Weapon should declare:
virtual void Shot(float angle) = 0;
and then each subclass should implement the virtual method.
Edit: Oh, and you can't just assign constructors to one another, you need to instantiate a concrete subclass, i.e:
Weapon *weapon = new Uzi();
as mentioned in several other answers.

Adding class functionality via composition

Suppose we have an abstract class Element from which classes Triangle and Quadrilateral are derived from.
Suppose yet that these classes are used in conjunction with interpolation methods that depend on the shape of the element. So, basically we create an abstract class InterpolationElement from which we derive InterpolationTriangle and InterpolationQuadrilateral.
Then, to include the interpolation functionality in the Triangle and Quadrilateral classes, we add a const-reference data member in class Element of type InterpolationElement, that is:
class Element
{
public:
Element(const InterpolationElement& interp);
const InterpolationElement& getInterpolation() const;
private:
const InterpolationElement& interpolation;
};
We then create a method (as described by Scott Meyers, Effective C++) that instanciate a local static object of class InterpolationTriangle as
const InterpolationTriangle& getInterpolationTriangle()
{
static InterpolationTriangle interpolationTriangle;
return interpolationTriangle;
}
So that class Triangle can be constructed like:
class Triangle : public Element
{
public:
Triangle() : Element( getInterpolationTriangle() ) {}
};
Here is my question: is this approach correct in order to incorporate interpolation methods on my class Element? Is this used in professional scenarios?
I could implement directly all the interpolation methods on class Element (as pure virtual) and the override them in the derived classes Triangle and Quadrilateral. However, this approach seems to me to be cumbersome, since every time I need to improve or implement new interpolation functionalities I would have to do that on these classes. Moreover, the classes get bigger and bigger (many methods) using this approach.
I would like to hear from you some tips and comments
Thanks in advance.
Additional details:
class InterpolationElement
{
public:
InterpolationElement();
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
}
class InterpolationTriangle : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
class InterpolationQuadrilateral : public InterpolationElement
{
public:
InterpolationTriangle () {}
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
:
virtual double interpolationMethod1(...) { // interpolation for quadrilateral}
}
The classes are used in conjunction with interpolation methods. Why do those methods need to be in a singleton object? The singleton here looks very problematic.
class Element
{
public:
virtual double interpolationMethod1(...) = 0;
:
virtual double interpolationMethodN(...) = 0;
};
class Triangle : public Element
{
public:
virtual double interpolationMethod1(...) { // interpolation for triangle }
:
virtual double interpolationMethodN(...) { // interpolation for triangle }
}
Also, welcome to SO!
This is reminiscent of a question that I had answered here. The same idea about the separation of data containers and the strategies.
There is one little issue with your proposal: you have added an interpolation related method to your base class and you've changed the constructor...
So first of all, if you wish to do it this way, here is how you should do it:
class Element
{
public:
private:
// similar signature to a `clone` method
virtual InterpolationElement* interpolation() const = 0;
};
class Triangle
{
public:
private:
virtual InterpolationTriangle* interpolation() const
{
return new InterpolationTriangle();
}
};
There are 2 advantages here:
It's no longer necessary to change the constructor of each of the derived objects
The strategy object is no longer const, which allows it to maintain state during the computation... like a reference to the current object being interpolated.
However, this still requires to change the Element class, and each of its derived classes. Doesn't it bother you ;) ?
Well, it's time (for once) to call upon a Design Pattern: Visitor.
It's a little different from the strategy idea, relying on double dispatch to work properly. However it allows you to tweak the hierarchy of Elements ONCE (with an accept method) and then to add as many operations as you wish. And that is great.
You can always mess a little bit with templates.
First we have a top class.
class Element {
public:
virtual void calculate() const = 0;
};
... but then we also have a class in the middle of the hierarchy which is actually a template. Template can't be the top level class, as templates with different parameters are different classes. The idea is that we give an interpolation class as a type parameter to the element.
template <typename Interpolation>
class Element_Impl : public Element {
protected:
Interpolation m_interpolation;
};
And interpolation classes. Notice, they aren't siblings, because they don't need to.
class InterpolationTriangle {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
double interpolate(double a, double b) const {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
And finally the real elements and the small main procedure.
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
m_interpolation.interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
m_interpolation.interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
Summary:
you can easily switch interpolation class for each element if needed.
there aren't double vtable access (first for Element's calculate and then for InterpolationElement's intepolate methods) as in the Matthieu's example. Each element knows at compile time which interpolation class it is using.
Element_Impl is an ugly bit, but it saves us from copypasta. You can expand it even further by implementing interpolation method wrappers
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
One way is to use static methods, and defining a wrapper in Element_Impl - still only in one place.
class Element {
public:
virtual void calculate() const = 0;
};
template <typename Interpolation>
class Element_Impl : public Element {
protected:
void interpolate(double, double) const {
Interpolation::interpolate(1, 1);
}
};
class InterpolationTriangle {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation triangle" << std::endl;
}
};
class InterpolationQuadrilateral {
public:
static double interpolate(double a, double b) {
std::cout << "interpolation quadrilateral" << std::endl;
}
};
class Triangle : public Element_Impl<InterpolationTriangle> {
public:
void calculate() const {
interpolate(1.0, 2.0);
}
};
class Quadrilateral : public Element_Impl<InterpolationQuadrilateral> {
public:
void calculate() const {
interpolate(2.0, 3.0);
}
};
int main() {
const Element &a = Triangle();
const Element &b = Quadrilateral();
a.calculate();
b.calculate();
}
What first comes to my mind is the GoF Design Pattern Visitor
From what I understand of your problem, this pattern is conceived to exactly solve this issue.
Each Visitor object defines an interpolation technique, or an algorithm to apply to your object.
Thus the Element class doesn't grow at all with each new functionnality. Once in place, the Visitor pattern enables to enrich functionnality without touching to the Base class definition.