I have a class hierarchy that I designed for a project of mine, but I am not sure how to go about implement part of it.
Here is the class hierarchy:
class Shape { };
class Colored { // Only pure virtual functions
};
class Square : public Shape { };
class Circle : public Shape { };
class ColoredSquare : public Square, public Colored { };
class ColoredCircle : public Circle, public Colored { };
In part of my project, I have a std::vector of different type shapes. In order to run an algorithm though, I need to put them in a std::vector of colored objects (all of which are derived types of different concrete shapes, so I need a method to cast a Square into a ColoredSquare and a Circle into a ColoredCircle at runtime.
The tricky thing is that the 'shape' classes are in a different library than the 'colored' classes.
What is the best method to acomplish this? I have thought about doing a dynamic_cast check, but if there is a better way, I would rather go with that.
Edit 1:
Here's a bit better of an Example:
class Traceable {
public:
// All virtual functions
virtual bool intersect(const Ray& r) = 0;
// ...
};
class TraceableSphere : public Sphere, public Traceable {
};
class IO {
public:
// Reads shapes from a file, constructs new concrete shapes, and returns them to
// whatever class needs them.
std::vector<Shape*> shape_reader(std::string file_name);
};
class RayTracer {
public:
void init(const std::vector<Shape*>& shapes);
void run();
private:
std::vector<Traceable*> traceable_shapes;
};
void RayTracer::init(const std::vector<Shape*>& shapes) {
// ??? traceable_shapes <- shapes
}
void RayTracer::run() {
// Do algorithm
}
You could use the decorator pattern:
class ColorDecorator public Colored
{
ColorDecorator(Shape* shape): m_shape(shape) {}
... //forward/implement whatever you want
};
If you want to store a Square in a Colored vector, wrap it in such a decorator.
Whether this makes sense is questionable though, it depends on your design and the alternatives. Just in case, also check out the visitor pattern (aka double dispatch) which you could use to just visit a subset of objects in a container or treat them differently depending on their type.
Looks like you are going to design the class library in a "is-a" style, welcome to the Inheritance-Hell.
Can you elaborate a bit about your "algorithm" ?
Typically it is bad design if you need to "type-test" on objects, since that is what you want to avoid with polymorphism. So the object should provide the proper implementation the algorithm uses (design-pattern: "strategy"), advanced concepts utilize "policy-based class design".
With careful design, you can avoid casting. In particular, care for SRP. Implement methods carefully so that they use a single Interface to achieve a single goal/fulfill a single responsibility. You have not posted anything about the algorithms or how the objects will be used. Below is a hypothetical sample design:
class A {
public:
void doSomeThing();
};
class B{
public:
void doSomeOtherThing();
};
class C:public A,public B{};
void f1( A* a){
//some operation
a->doSomeThing();
//more operation
}
void f2(B* b){
//some operation
b->doSomeOtherThing();
//more operation
}
int main(int argc, char* argv[])
{
C c;
f1(&c);
f2(&c);
return 0;
}
Note using the object c in different context. The idea is to use only the interface of C that is relevant for a specific purpose. This example can have classes instead of the functions f or f2. For example, you have some Algorithms classes that do some operation using the objects in the inheritance hierarchy, you should create the classes such that they perform a single responsibility, which most of the time requires a single interface to use, and then you can create/pass objects as instance of that interface only.
Object-oriented programming only makes sense if all implementations of an interface implement the same operations in a different way. Object-orientation is all about operations. You have not shown us any operations, so we cannot tell you if object-orientation even makes sense for your problem at all. You do not have to use object-oriented programming if it doesn't make sense, especially in C++, which offers a few other ways to manage code.
As for dynamic_cast -- in well-designed object-oriented code, it should be rare. If you really need to know the concrete type in some situation (and there are such situations in real-life software engineering, especially when you maintain legacy code), then it's the best tool for the job, and much cleaner than trying to reimplement the wheel by putting something like virtual Concrete* ToConcrete() in the base class.
I think the simplest & cleanest solution for you would be something like the following similar to what Chris suggests at the end.
class Shape {
virtual Colored *getColored() {
return NULL;
}
};
class Colored { // Only pure virtual functions
};
class Square : public Shape { };
class Circle : public Shape { };
class ColoredSquare : public Square, public Colored {
virtual Colored *getColored() {
return this;
}
};
class ColoredCircle : public Circle, public Colored {
virtual Colored *getColored() {
return this;
}
};
I do not completely understand this statement though
" The tricky thing is that the 'shape' classes are in a different library than the 'colored' classes."
How does this not allow you to do what's being suggested here (but still allow you to create a class ColoredSquare) ?
Related
Currently I'm trying to understand "evilness" of MI. I've just watched a video on youtube where a js guy speaks against inheritance. Here is his example (I've rewrite it in C++):
struct Robot
{ void drive(); };
struct MurderRobot : public Robot
{ void kill(); };
struct CleanerRobot : public Robot
{ void clean(); };
struct Animal
{ void poop(); };
struct Dog : public Animal
{ void bark(); };
struct Cat : public Animal
{ void meow(); };
Then he suggested a new class MurderRobotDog, which, from his point of view, can't be done gracefully by means of inheritance. Surely, it can't be done by means of single inheritance. But I don't see any problem to do that with MI.
I think we could create a base class BarkingObject, which would have all barking stuff. Then the Dog inherits from the Animal, which has common poop(), and from the BarkingObject. And when you need a killing dog-robot, it must inherit from the BarkingObject and the MurderRobot. It makes more sense. The MurderRobotDog can't inherit from a live creature, because then it becomes alive and that contradicts with the definition of a robot. Of course, for that you have to use multiple inheritance that is considered to be EVIL by many people. It's unfortunate, as it seems we can't efficiently reuse different unrelated (you don't need poop() in order to bark(), and the robot case confirms this assertion) functionality without it.
What is your arguments against my suggestion?
A multiple inheritance implementation is an old-fashioned way of solving these sorts of problems.
Composition is the new way.
You define interfaces which describe a particular behaviour or set of behaviours:
struct Murderer
{
virtual ~Murderer() = default;
void kill();
};
struct Pooper
{
virtual ~Pooper() = default;
void poop();
};
Actual things, like a cat, dog, or robot, inherit (i.e. implement) these interfaces accordingly. You use a dynamic_cast or similar runtime technique to query an object for an interface before making the appropriate action.
I am trying to understand the syntactic difference between composition and inheritance in C++.
I'm hoping someone will provide two simple examples. One example of a class that uses composition and one of a class that uses inheritance.
Sure, why not? Since I like robots, let's make a robot that can walk around and grab things. We'll make one robot using inheritance, and another robot using composition:
class Legs {
public:
void WalkAround() {... code for walking around goes here...}
};
class Arms {
public:
void GrabThings() {... code for grabbing things goes here...}
};
class InheritanceRobot : public Legs, public Arms {
public:
// WalkAround() and GrabThings() methods are implicitly
// defined for this class since it inherited those
// methods from its two superclasses
};
class CompositionRobot {
public:
void WalkAround() {legs.WalkAround();}
void GrabThings() {arms.GrabThings();}
private:
Legs legs;
Arms arms;
};
Note that at least for this example, the CompositionRobot is usually considered to be the better approach, since inheritance implies an is-a relationship, and a robot isn't a particular kind of Arms and a robot isn't a particular kind of Legs (rather a robot has-arms and has-legs).
To expand a little on #jeremy-friesner's answer (and mostly reuse his code), a lot of the time composition is implemented using more classes than that. Essentially the Legs and Arms classes would be implementations of an interface. This makes it easy to inject those dependencies and, hence, mock/stub them out when unit testing the composite object. Then you'd have something like (ignoring virtual destructor...) :
class Walker // interface
{
public:
virtual void Walk() = 0;
}
class Legs : public Walker
{
public:
void Walk() {... code for walking around goes here...}
}
class Grabber // Interface
{
public:
virtual void GrabThings() = 0;
}
class Arms : public Grabber
{
public:
void GrabThings() {... code for grabbing things goes here...}
}
class InheritanceRobot : public Legs, public Arms
{
public:
// Walk() and GrabThings() methods are implicitly
// defined for this class since it inherited those
// methods from its two superclasses
};
class CompositionRobot
{
public:
CompositionRobot(Walker& walker, Grabber& grabber)
: legs(walker),
arms(grabber)
{}
void Walk() {legs.Walk();}
void GrabThings() {arms.GrabThings();}
private:
Walker& legs;
Grabber& arms;
};
So the actual implementation used for legs and arms could be set at run-time instead of compile time.
As an aside, I only wrote this as an answer, rather than a comment on Jeremy's answer, to benefit from the code formatting so, if you feel like up-voting it, please do Jeremy's too.
HTH
UPDATE Sep 14, 2021:
One thing I've noticed in this answer is that I've conflated composition and aggregation. In composition, if the parent object ceases to exist, then so does the child object whereas, in aggregation, the child objects may exist after the parent is destroyed. The description I've given, where references to instances of the child objects are passed in the CompositionRobot constructor implies an aggregation relationship rather than composition. However, if you were to use std::unique_ptr() when defining the parameters and creating the objects, and std::move() when they're stored in the constructor of CompositionRobot, the effect would be much the same as in Jeremy's answer where the objects (rather than a pointer or a reference to them) are defined as class members.
I need to develop a C++ solution to represent an object with features, where the objects and features are represented by different objects, but the actual implementation of the association is implemented in a derived class which exists to encapsulate an external implementation. I know that this kind of thing is typical of inheritance-related problems, so I want opinions on the correct solution. The implementation part should be seen as a sort of API boundary -- the user code should not see it, or see it only once in order to select the implementation.
Here's an example:
#include <cstdio>
// External implementation 1
class SomeShape {};
class SomeBody { public: SomeShape *shape; };
// External implementation 2
class OtherShape {};
class OtherBody { public: OtherShape *shape; };
//////////////
class Shape
{
public:
virtual const char *name() { return "Shape"; }
};
class Body
{
public:
virtual void setShape(Shape *s) = 0;
};
class Factory
{
public:
virtual Shape *makeShape() = 0;
virtual Body *makeBody() = 0;
};
//////////////
class AShape : public Shape
{
public:
SomeShape *someShape;
virtual const char *name() { return "AShape"; }
};
class ABody : public Body
{
protected:
SomeBody *someBody;
AShape *shape;
public:
ABody() { someBody = new SomeBody; }
virtual void setShape(Shape *s)
{
shape = static_cast<AShape*>(s);
printf("Setting shape: %s\n", s->name());
someBody->shape = shape->someShape;
}
};
class AFactory : public Factory
{
public:
virtual Shape *makeShape()
{ return new AShape(); }
virtual Body *makeBody()
{ return new ABody(); }
};
//////////////
class BShape : public Shape
{
public:
OtherShape *otherShape;
virtual const char *name() { return "BShape"; }
};
class BBody : public Body
{
protected:
OtherBody *otherBody;
BShape *shape;
public:
BBody() { otherBody = new OtherBody; }
virtual void setShape(Shape *s)
{
shape = static_cast<BShape*>(s);
printf("Setting shape: %s\n", s->name());
otherBody->shape = shape->otherShape;
}
};
class BFactory : public Factory
{
public:
virtual Shape *makeShape()
{ return new BShape(); }
virtual Body *makeBody()
{ return new BBody(); }
};
Thus, the role of the above is to allow the user to instantiate Body and Shape objects, which exist to manage associating underlying implementations SomeShape/SomeBody or OtherShape/OtherBody.
Then, a main function exercising both implementations could be,
int main()
{
// Of course in a real program we would return
// a particular Factory from some selection function,
// this should ideally be the only place the user is
// exposed to the implementation selection.
AFactory f1;
BFactory f2;
// Associate a shape and body in implementation 1
Shape *s1 = f1.makeShape();
Body *b1 = f1.makeBody();
b1->setShape(s1);
// Associate a shape and body in implementation 2
Shape *s2 = f2.makeShape();
Body *b2 = f2.makeBody();
b2->setShape(s2);
// This should not be possible, compiler error ideally
b2->setShape(s1);
return 0;
}
So, the parts that I am not happy about here are the static_cast<> calls in setShape(), because they build in an assumption that the correct object type has been passed in, without any compile-time type checking. Meanwhile, setShape() can accept any Shape, when in reality only a derived class should be accepted here.
However, I don't see how compile-time type checking could be possible if I want the user code to operate on the Body/Shape level and not the ABody/AShape or BBody/BShape level. However, switching the code so that ABody::setShape() accepts only an AShape* would make the whole factory pattern useless, for one thing, and would force the user code to be aware of which implementation is in use.
In addition it seems like the A/B classes are an extra level of abstraction over Some/Other, which exist only to support them at compile time, yet these are not intended to be exposed to the API, so what's the point... they serve only as a kind of impedance-matching layer, forcing both SomeShape and OtherShape into the Shape mold.
But what are my alternative choices? Some run-time type checking could be used, such as dynamic_cast<> or an enum, but I'm looking for something a little more elegant, if possible.
How would you do this in another language?
Analysis of your design issue
Your solution implements the abstract factory design pattern, with:
AFactory and BFactory are concrete factories of the abstract Factory
ABody and AShape on one hand and BBody and BShape on the other hand are concrete products of abstract products Body and Shape.
The Axxx classes form a familiy of related classes. So do the Bxxx classes.
The issue you worry about is that an the method Body::setShape() depends on an abstract shape argument, whereas the concrete implementation expects in reality a concrete shape.
As you've rightly pointed out, the downcast to the concrete Shape suggests a potential design flaw. And it will not be possible to catch the errors at compile-time, because the whole pattern is designed to be dynamic and flexible at run time, and the virtual function can't be templatized.
Alternative 1: make your current design a little bit safer
Use the dynamic_cast<> to check at runtime if the downcast is valid. Consequence:
the ugly casting is very well isolated in a single function.
the runtime check is only done when necessary, i.e. the only time you set the shape.
Alternative 2: adopt a design with strong isolation
A better design, would be to isolate the different products. So one product class would only use the abstract interface of the other classes of the same family and ignore their concrete specificity.
Consequences:
very robust design enforcing superior separation of concerns
you could factorize the Shape* member at the level of the abstract class, and perhaps even de-virtualize setShape().
but this comes at expense fo rigidity: you couldn't make use of family specific interface. This could be very embarassing, if for example the goal is that the family represents a native UI, knowing that products are highly interdependent and need to use native API (that's the typical example in the book of the Gang of 4).
Alternative 3: templatize dependent types
Opt for a template based implementation of your abstract factory. The general idea, is that you define the internal dependencies between products, using a template implementation.
So in your example Shape, AShape and BShape are unchanged as there is no dependency to other produts. But Body depends on a Shape, ad you want to have ABody depending on AShape, whereas BBody should depend on BShape.
The trick is then to use a template instead of an abstract class:
template<class Shape>
class Body
{
Shape *shape;
public:
void setShape(Shape *s) {
shape=s;
printf("Setting shape: %s\n", s->name());
}
};
Then you would define ABody by deriving it from Body<AShape>:
class ABody : public Body<AShape>
{
protected:
SomeBody *someBody;
public:
ABody() { someBody = new SomeBody; }
};
This is all very nice, but how shall this work with the abstract factory ? Well same principle: templatize instead of virtualize.
template <class Shape, class Body>
class Factory
{
public:
Shape *makeShape()
{ return new Shape(); }
Body *makeBody()
{ return new Body(); }
};
// and now the concrete factories
using BFactory = Factory<BShape, BBody>;
using AFactory = Factory<AShape, ABody>;
The consequence is that you have to know at compile time which concrete factory and concrete products you intend to use. THis can be done using C++11 auto :
AFactory f1; // as before
auto *s1 = f1.makeShape(); // type is deduced from the concrete factory
auto *b1 = f1.makeBody();
b1->setShape(s1);
With this approach you will no longuer be able to mixup products of different families. The following statement will cause an error:
b2->setShape(s1); // error: no way to convert an AShape* to a BShape*
And here an online demo
I'm currently learning C++ and for this I'm writing a simple image-converter.
I would like to have a base image class that contains different memorylayouts of the image, say DXTn or BMP.
How do I properly design my class that can contain these different datatypes?
Is there a better way of storing the memory in a (smart)pointer?
class Image
{
public:
void loadDXT() { }
void loadBMP() { }
private:
char* data1;
std::unique_ptr< char* > data2;
}
Or would it be better to derive a more specific classfrom a simple baseclass:
class baseImage
{
public:
enum imgType { BMP , DXT };
void load() = 0;
}
class BMPImage : public baseImage
{
//bmp specific stuff here
}
This isn't only specific to this imageclass, I'm in general curious how do I design classes that contain different data member.
Thank you.
I agree with jwg a virtual abstract interface would make your life easier.
For example:
class BaseImage//base class
{
public:
virtual void DoThingsRelatedToAllImages_1()=0;
virtual void DoThingsRelatedToAllImages_2()=0;
//...and so on and whatever else
private:
int DataUsedForAllImageTypes;
};
//this is our child class
class Bmp: public BaseImage
{
private:
int DataUsedOnlyForBmpTypeImages;
};
void Bmp::DoThingsRelatedToAllImages_1()
{
//Do Whatever this function should do for a bitmap
}
void Bmp::DoThingsRelatedToAllImages_2()
{
//Do Whatever this function should do for a bitmap
}
Just keep in mind than an abstract class cannot be instantiated because it has no implementation. If you go with a virtual class not an abstract class you in theory could have typeless image classes to work with if you needed it. all you would need to do is provide a basic implementation to your virtual class.
For example:
class BaseImage//base class
{
public:
virtual void DoThingsRelatedToAllImages_1();
virtual void DoThingsRelatedToAllImages_2();
//...and so on and whatever else
private:
int DataUsedForAllImageTypes;
};
void BaseImage::DoThingsRelatedToAllImages_1()
{
//Do Whatever this function should do for a base image
}
void BaseImage::DoThingsRelatedToAllImages_2()
{
//Do Whatever this function should do for a base image
}
//this is our child class
class Bmp: public BaseImage
{
private:
int DataUsedOnlyForBmpTypeImages;
};
void Bmp::DoThingsRelatedToAllImages_1()
{
//Do Whatever this function should do for a bitmap
}
void Bmp::DoThingsRelatedToAllImages_2()
{
//Do Whatever this function should do for a bitmap
}
Hopefully this was a helpful example.
I would also say that Template classes could be very useful but I will leave you to figure that out as I do not really want to go into that right now.
Good luck, Let me know if i can clarify anything i said.
I would say that the second method is definitely what you need. You are basically specifying an interface - what you would use an abstract class for in C++. The base class should contain all the functions that you think every image should be able to provide - probably as pure virtual functions since there is no 'general image' which implements these the same way for any image. (You might have things like common metadata which have the same structure for every image type, and these could be dealt with by methods in the base class.)
Then each class will implement the virtual functions based on its own private data stored in the way that makes sense for that type of image. If some image types share some, but not all operations, you could have several layers of inheritance, eg RasterImage inherits from Image and BMPImage and PNGImage inherit from RasterImage.
There are libraries around that do a lot of this stuff to permit rendering of graphs, vector objects, etc. into multiple formats. You probably don't want to use a big outside library since you are doing this to teach yourself, but you might like to look at how one is structured to get some ideas. (Note that some graphics libraries will justifiably have a much more complex and flexible structure then you probably want to imitate. If there are so many layers of abstraction and inheritance that you can't keep track of them, it might not be the best source to learn by example from.)
Suppose I have following inheritance tree:
SDLBullet inherits from Bullet inherits from Entity
EnemyBullet inherits form Bullet inherits from Entity
Now I need a new class, SDLEnemyBullet, which needs the draw as implemented in SDLBullet, and the collision as implemented in EnemyBullet. How would I do this? Is this to be solved using multiple inheritance? If not, feel free to edit my question and title. If so, how would I implement such thing?
Some code examples below:
class Entity {
bool collision(Entity) = 0;
void draw() = 0;
}
class Bullet : Entity {
bool collision(Entity) {/*some implementation*/};
void draw() {/*draw me*/};
}
class SDLBullet : Bullet {
void draw() {/*draw me using SDL*/};
}
class EnemyBullet : Bullet {
bool collision(Entity) {/*if Entity is a fellow enemy, don't collide*/};
}
class SDLEnemyBullet : ????? {
/*I need SDLBullet::draw() here*/
/*I need EnemyBullet::collision(Entity) here*/
/*I certainly do not want EnemyBullet::draw nor SDLBullet::collision here*/
}
Any help is much appreciated!
(BTW: This is a school project, and an inheritance tree like this was suggested to us. No one is stopping us from doing it different and better. Thats why I asked the question.)
The textbook solution involves multiple and virtual inheritance.
class SDLBullet : public virtual Bullet {
void draw() {/*draw me using SDL*/};
};
class EnemyBullet : public virtual Bullet {
bool collision(Entity) {/*if Entity is a fellow enemy, don't collide*/};
};
class SDLEnemyBullet : public SDLBullet, public EnemyBullet {
// just one Bullet subobject here
};
Normally, collision stuff is done using multiple dispatch, or in C++, who hasn't this feature, using the visitor pattern.
BUT
why don't you have a hierarchy like this instead ?
class Entity;
class Bullet : public Entity
{
public:
virtual draw();
}
class FriendlyBullet : public Bullet
{
public:
bool collide(EnnemyBullet*);
bool collide(FriendlyBullet*);
}
class EnnemyBullet : public Bullet
{
public:
bool collide(EnnemyBullet*);
bool collide(FriendlyBullet*);
}
This would work too, and wouldn't require multidispatch or multiple inheritance
You need to specify a comma separated list of the super classes:
class SDLEnemyBullet : public SDLBullet, public EnemyBullet {
/*I need SDLBullet::draw() here*/
/*I need EnemyBullet::collision(Entity) here*/
/*I certainly do not want EnemyBullet::draw nor SDLBullet::collision here*/
}
It looks like you're making a game (engine). To avoid the need for complex inheritance structures like this favor composition over inheritance for entities i.e. Have an entity object that contains separate 'component' objects for rendering etc. That way you can mix and match the components however you like without having an explosion of classes with all the different combinations of super classes.
Here's a good article on the subject: http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/
Prefer composition over inheritance
You don't need inheritance to combine stuff that's not related like that. Make up basic objects (entities?) for game logic, physics, sound, input, graphics (which may use inheritance) and combine those a GameObject which just has an array of said objects.
Some nifty cross-linking is useful since they will all share a Frame or Transform, but that can be done during creation by iterating over all other objects and using dynamic_cast... (it's useful if you do not need to depend on initialization order).
But there's really no need to build this with inheritance. It doesn't fit your usecase properly. (Although virtual inheritance is useful, it's not a good thing to use inheritance to force different things to become the same, i.e. making everything be a something, instead of being made up of different parts (render, damage, sound, etc...).
Read this and this for more info, or just click the title to google for it. :)