I'm trying to use C++ abstract base class in the way similar with Java interface. Supposed that we have following interface classes with only pure virtual functions:
class Shape { virtual double area()=0; };
class Square : public Shape { virtual void setLength(double length)=0; };
class Rectangle : public Square { virtual void setWidth(double width)=0; };
and I try to implement Square and Rectangle the following way:
class SquareImpl : public Square { /*implementation*/ };
class RectangleImpl : public SquareImpl, Rectangle { /*implementation*/ };
Where RectangleImpl inherits both SquareImpl and Rectangle to reuse, say, SquareImpl::area(). However when I try to compile, two problems arise: Firstly, all methods in SquareImpl do not get inherited properly and I have to manually reimplement RectangleImpl::area() and RectangleImpl::setLength(). Secondly, this still introduces the diamond problem that Shape is ambiguous base of RectangleImpl.
I could compile the code if I virtually inherit Square from Shape, but I don't think the performance will scale with more derived interfaces added. Also strangely, RectangleImpl still doesn't inherit SquareImpl::setLength() although SquareImpl::area() is inherited well. (ignore the practicality here)
Another solution might be to make interfaces independent of each other, i.e. to make Square not inherited from Shape. But doing so will make me lose access to methods in Shape if I define functions that take a Square* pointer. It will also make static_cast impossible between Shape and Square.
So my question is, is there any other design pattern in C++ to solve this kind of parallel inheritance between interface classes and implementation classes, without requiring virtual inheritance?
(edit clarification: the example code above are just my dummy illustration on parallel inheritance between interfaces and implementations. I understand that there are better ways to implement shapes but my problem is not on how to implement shapes.)
What you have here is the case of the Diamond Problem, which can happen in any OO language that allows multiple inheritance. This, by the way, is one reason why the designers of Java decided not to have multiple inheritance, and came up with the notion of an interface.
The way C++ deals with the diamond problem is Virtual Inheritance.
And, as codymanix pointed out, the square and the rectangle is a notoriously bad example for object oriented design, because as far as OO is concerned a square is not a rectangle.
Couple more points. First, The term for what you are doing here is multiple inheritance, not "parallel inheritance". Second, in this particular case it really makes little sense to have a class Square and a class SquareImpl. If you think you may have different implementations of Square, you should just have one base class which provides a default implementation and virtual functions that can be overridden by a derived class if necessary. In other words, you should roll Square and SquareImpl into one class with virtual functions.
You certainly can use an abstract C++ class like a Java interface, but most of the time there is no reason for it. Interfaces were added to Java precisely as a way to get around the lack of multiple inheritance. In C++ you can just go ahead and use multiple inheritance, although you should always do that very judiciously.
You are by far not the first who met this problem. See A Square Is Not a Rectangle to give one example.
After rethinking for a night and referring to the solution sean provided at Looking for a better way than virtual inheritance in C++, I came out with the following solution.
Here I redefine the problem to be more abstract to avoid the confusion we had on shapes. We have a Ball interface that can roll, a FooBall interface that contains Foo specific methods, and a FooBarBall interface that is also a FooBall and contains both Foo specific and Bar specific methods. Same as the original problem, we have a FooBall implementation and we wish to derive it to cover Bar specific methods as well. but inheriting both the interface and implementation will introduce diamond inheritance.
To solve the problem, instead of directly putting Foo and Bar specific methods into the derived Ball interfaces, I put a single method into a derived FooBall interface that converts the object into a Foo object through the toFoo() method. This way, implementations can mix in the independent Foo and Bar interface without introducing diamond inheritance.
Still, not all codes can be eliminated to derive all Bars from Foos freely. We have to still write independent implementations of Ball, FooBall, and FooBarBall that do not inherit from each others. But we can use the composite pattern to wrap the real Foo and Bar objects that are implemented differently. This way we can still eliminate quite a lot of code if we have a lot of implementations of Foo and Bar.
#include <stdio.h>
class Ball {
public:
// All balls can roll.
virtual void roll() = 0;
// Ball has many other methods that are not
// covered here.
virtual inline ~Ball() {
printf("deleting Ball\n");
};
};
class Foo {
public:
virtual void doFoo() = 0;
// do some very complicated stuff.
virtual void complexFoo() = 0;
virtual inline ~Foo() {};
};
/**
* We assume that classes that implement Bar also
* implement the Foo interface. The Bar interface
* specification failed to enforce this constraint
* by inheriting from Foo because it will introduce
* diamond inheritance into the implementation.
**/
class Bar {
public:
virtual void doBar() = 0;
virtual void complicatedBar() = 0;
virtual inline ~Bar() {};
};
class FooBall : public Ball {
public:
virtual Foo* toFoo() = 0;
virtual inline ~FooBall() {};
};
/**
* A BarBall is always also a FooBall and support
* both Foo and Bar methods.
**/
class FooBarBall : public FooBall {
public:
virtual Bar* toBar() = 0;
virtual inline ~FooBarBall() {};
};
/* Composite Implementation */
class FooImpl_A : public Foo {
public:
virtual void doFoo() {
printf("FooImpl_A::doFoo()\n");
};
virtual void complexFoo() {
printf("FooImpl_A::complexFoo()\n");
}
virtual inline ~FooImpl_A() {
printf("deleting FooImpl_A\n");
}
};
class FooBarImpl_A : public FooImpl_A, public Bar {
public:
virtual void doBar() {
printf("BarImpl_A::doBar()\n");
}
virtual void complicatedBar() {;
printf("BarImpl_A::complicatedBar()\n");
}
virtual inline ~FooBarImpl_A() {
printf("deleting FooBarImpl_A\n");
}
};
/* Composite Pattern */
class FooBarBallContainer : public FooBarBall {
public:
/* FooBarBallImpl_A can take any class that
* implements both the Foo and Bar interface,
* including classes that inherit FooBarImpl_A
* and other different implementations.
*
* We'll assume that realFoo and realBar are
* actually the same object as Foo methods have
* side effect on Bar methods. If they are not
* the same object, a third argument with false
* value need to be supplied.
*/
FooBarBallContainer( Foo* realFoo, Bar* realBar, bool sameObject=true ) :
_realFoo(realFoo), _realBar(realBar), _sameObject(sameObject) {}
virtual void roll() {
// roll makes use of FooBar methods
_realBar->doBar();
_realFoo->complexFoo();
}
virtual Foo* toFoo() {
return _realFoo;
}
virtual Bar* toBar() {
return _realBar;
}
virtual ~FooBarBallContainer() {
delete _realFoo;
// Check if realFoo and realBar are
// not the same object to avoid deleting
// it twice.
if(!_sameObject) {
delete _realBar;
}
}
private:
Foo* _realFoo;
Bar* _realBar;
bool _sameObject;
};
/* Monolithic Implmentation */
class FooBarBallImpl_B : public FooBarBall,
public Foo, public Bar {
public:
virtual void roll() {
complicatedBar();
doFoo();
}
virtual Foo* toFoo() {
return (Foo*) this;
}
virtual Bar* toBar() {
return (Bar*) this;
}
virtual void doFoo() {
printf("FooBarBallImpl_B::doFoo()\n");
}
virtual void complexFoo() {
printf("FooBarBallImpl_B::complexFoo()\n");
}
virtual void doBar() {
printf("FooBarBallImpl_B::doBar()\n");
}
virtual void complicatedBar() {
printf("FooBarBallImpl_B::complicatedBar()\n");
}
};
/* Example usage of FooBarBall */
void processFooBarBall(FooBarBall *ball) {
Foo *foo = ball->toFoo();
foo->doFoo();
ball->roll();
Bar *bar = ball->toBar();
bar->complicatedBar();
}
main() {
FooBarImpl_A *fooBar = new FooBarImpl_A();
FooBarBall *container = new FooBarBallContainer(fooBar, fooBar);
printf
processFooBarBall(container);
delete container;
FooBarBallImpl_B *ball = new FooBarBallImpl_B();
processFooBarBall(ball);
// we can even wrap FooBarBallImpl_B into the container
// but the behavior of roll() will become different
container = new FooBarBallContainer(ball, ball);
processFooBarBall(container);
delete container;
}
Square is not Rectangle, and Rectangle is not Square. Only thing they have in common is that they are Shapes. So:
class Square : public Shape {...};
class Rectangle : public Shape {...};
Their initialization functions are different, Square::setSide(double) and Rectangle::setLengthAndWidth(double, double). You don't need *Impl classes. Do your stuff in in Square and Rectangle.
I think you should be looking for virtual inheritance here so that you only have a single instance of shape underneath it all - this seems obvious from a semantic point of view - i.e. The shape that square and rectangleimpl is clearly the same shape.
Not really sure of the performance issue you mention - that doesn't seem an issue to me (in the sense that their is no extra overhead other than that of calling any v-function).
I don't see why you can't access the setLength from square - difficult to see why you might be experiencing this and you don;t have source for the implementations.
Your problem is Rectangle->Square->Shape knows nothing about the SquareImpl so it cannot use these functions to satisfy its abstract function requirements.
The easiest way is to not mix your interface and implementation inheritance when they are closely bound like this. Make RectangleImpl inherit from the Square and Rectangle interfaces. If SquareImpl and RectangleImpl are replicating too much of each other's code, use a class that does all this work and have as a member function in each implementation.
Related
I'm somewhat new to the more advanced features of C++. Yesterday, I posted the following question and I learned about virtual inheritance and the dreaded diamond of death.
Inheriting from both an interface and an implementation C++
I also learned, through other links, that multiple inheritance is typically a sign of a bad code design and that the same results can usually be better achieved without using MI. The question is... I don't know what is a better, single-inheritance approach for the following problem.
I want to define an Interface for two types of Digital Points. An Input Digital Point and an Output Digital Point. The Interface is to be slim, with only what's required to access the information. Of course, the vast majority of properties are common to both types of digital points. So to me, this is a clear case of Inheritance, not Composition.
My Interface Definitions look something like this:
// Interface Definitions
class IDigitalPoint
{
public:
virtual void CommonDigitalMethod1() = 0;
};
class IDigitalInputPoint : virtual IDigitalPoint
{
public:
virtual void DigitialInputMethod1() = 0;
};
class IDigitalOutputPoint : virtual IDigitalPoint
{
public:
virtual void DigitialOutputMethod1() = 0;
};
My implementations look like this:
// Implementation of IDigitalPoint
class DigitalPoint : virtual public IDigitalPoint
{
public:
void CommonDigitalMethod1();
void ExtraCommonDigitalMethod2();
}
// Implementation of IDigitalInputPoint
class DigitalInputPoint : public DigitalPoint, public IDigitalInputPoint
{
public:
void DigitialInputMethod1();
void ExtraDigitialInputMethod2();
}
// Implementation of IDigitalOutputPoint
class DigitalOutputPoint : public DigitalPoint, public IDigitalOutputPoint
{
public:
void DigitialOutputMethod1();
void ExtraDigitialOutputMethod2();
}
So how could I reformat this structure, to avoid MI?
"multiple inheritance is typically a sign of a bad code design" - parents that are pure interfaces are not counted in regards to this rule. Your I* classes are pure interfaces (only contain pure virtual functions) so you Digital*Point classes are OK in this respect
(Multiple) inheritance and interfaces tend to needless complications of simple relations.
Here we need only a simple structure and few freestanding functions:
namespace example {
struct Point { T x; T y; }
Point read_method();
void write_method(const Point&)
void common_method(Point&);
void extra_common_method(Point&);
} // example
The common_method might be a candidate for a member function of Point.
The extra_common_method, which is not so common, might be a candidate for another class encapsulating a Point.
This is exactly the situation in which the standard library does use virtual inheritance, in the std::basic_iostream hierarchy.
So, it may be the rare case where it genuinely makes sense.
However, this depends on exactly the fine details you've removed for clarity, so it isn't possible to say for certain whether a better solution exists.
For example, why is an input point different from an output point? A DigitalPoint sounds like a thing with properties, that might be modeled by a class. A DigitalInputPoint, however, just sounds like ... a DigitalPoint somehow coupled to an input source. Does it have different properties? Different behaviour? What are they and why?
You can go to below link to understand more about multiple inheritance
Avoid Multiple Inheritance
Also, in your case, multiple inheritance makes sense!!.
You may use composition if you want.
Consider a different approach:
class DigitalPoint
{
public:
void CommonDigitalMethod1();
void ExtraCommonDigitalMethod2();
}
// Implementation of IDigitalInputPoint
class DigitalInputPoint
{
public:
void CommonDigitalMethod1();
void DigitialInputMethod1();
void ExtraDigitialInputMethod2();
}
// Implementation of IDigitalOutputPoint
class DigitalOutputPoint
{
public:
void CommonDigitalMethod1();
void DigitialOutputMethod1();
void ExtraDigitialOutputMethod2();
}
To be used like this:
template <class T>
void do_input_stuff(T &digitalInputPoint){
digitalInputPoint.DigitialInputMethod1();
}
You get an easier implementation with a clearer design and less coupling with most likely better performance. The only One downside is that the interface is implicitly defined by the usage. This can be mitigated by documenting what the template expects and eventually you will be able to do it in concepts to have the compiler check it for you.
Another downside is that you cannot have a vector<IDigitalPoint*> anymore.
Are you really sure that you need 3 interfaces?
class IDigitalPoint
{
public:
virtual void CommonDigitalMethod1() = 0;
};
enum class Direction : bool { Input, Output };
template <Direction direction>
class DigitalPoint : public IDigitalPoint
{
public:
void CommonDigitalMethod1() {}
void ExtraCommonDigitalMethod2() {}
virtual void DigitialMethod1() = 0;
};
class DigitalInputPoint : public DigitalPoint<Direction::Input>
{
public:
void DigitialInputMethod1() {}
void ExtraDigitialInputMethod2() {}
// This is like DigitialInputMethod1()
virtual void DigitialMethod1() override
{}
};
class DigitalOutputPoint : public DigitalPoint<Direction::Output>
{
public:
void DigitialOutputMethod1() {}
void ExtraDigitialOutputMethod2() {}
// This is like DigitialOutputMethod1()
virtual void DigitialMethod1() override
{}
};
You could use composition instead of inheritance. Live Example
If the child classes do not use functionality from DigitalPoint, then you can try using CRTP. It can be confusing if you don't understand CRTP, but it works like a charm when it fits properly. Live Example
There was an interesting problem in C++, but it was more about architecture.
There are many (10, 20, 40, etc) classes describing some characteristics (mix-in classes), for example:
struct Base { virtual ~Base() {} };
struct A : virtual public Base { int size; };
struct B : virtual public Base { float x, y; };
struct C : virtual public Base { bool some_bool_state; };
struct D : virtual public Base { string str; }
// ....
The primary module declares and exports a function (for simplicity just function declarations without classes):
// .h file
void operate(Base *pBase);
// .cpp file
void operate(Base *pBase)
{
// ....
}
Any other module can have code like this:
#include "mixing.h"
#include "primary.h"
class obj1_t : public A, public C, public D {};
class obj2_t : public B, public D {};
// ...
void Pass()
{
obj1_t obj1;
obj2_t obj2;
operate(&obj1);
operate(&obj2);
}
The question is how do you know what the real type of a given object in operate() is without using dynamic_cast and any type information in classes (constants, etc)? The operate() function is used with a big array of objects in small time periods and dynamic_cast is too slow for it and I don't want to include constants (enum obj_type { ... }) because this is not the OOP-way.
// module operate.cpp
void some_operate(Base *pBase)
{
processA(pBase);
processB(pBase);
}
void processA(A *pA)
{
}
void processB(B *pB)
{
}
I cannot directly pass a pBase to these functions. And it's impossible to have all possible combinations of classes, because I can add new classes just by including new header files.
One solution that came to mind, in the editor I can use a composite container:
struct CompositeObject
{
vector<Base *pBase> parts;
};
But the editor does not need time optimization and can use dynamic_cast for parts to determine the exact type. In operate() I cannot use this solution.
So, is it possible to avoid using a dynamic_cast and type information to solve this problem? Or maybe I should use another architecture?
The real problem here is about what you are trying to achieve.
Do you want something like:
void operate(A-B& ) { operateA(); operateB(); }
// OR
void operate(A-B& ) { operateAB(); }
That is, do you want to apply an operation on each subcomponent (independently), or do you wish to be able to apply operations depending on the combination of components (much harder).
I'll take the first approach here.
1. Virtual ?
class Base { public: virtual void operate() = 0; };
class A: virtual public Base { public virtual void operate() = 0; };
void A::operate() { ++size; } // yes, it's possible to define a pure virtual
class obj1_t: public A, public B
{
public:
virtual void operate() { A::operate(); B::operate(); }
};
Some more work, for sure. Notably I don't like the repetition much. But that's one call to the _vtable, so it should be one of the fastest solution!
2. Composite Pattern
That would probably be the more natural thing here.
Note that you can perfectly use a template version of the pattern in C++!
template <class T1, class T2, class T3>
class BaseT: public Base, private T1, private T2, private T3
{
public:
void operate() { T1::operate(); T2::operate(); T3::operate(); }
};
class obj1_t: public BaseT<A,B,C> {};
Advantages:
no more need to repeat yourself! write operate once and for all (baring variadic...)
only 1 virtual call, no more virtual inheritance, so even more efficient that before
A, B and C can be of arbitrary type, they should not inherit from Base at all
edit the operate method of A, B and C may be inlined now that it's not virtual
Disadvantage:
Some more work on the framework if you don't have access to variadic templates yet, but it's feasible within a couple dozen of lines.
First thing that comes to mind is asking what you really want to achieve... but then again the second thought is that you can use the visitor pattern. Runtime type information will implicitly be used to determine at what point in the hierarchy is the final overrider of the accept method, but you will not explicitly use that information (your code will not show any dynamic_cast, type_info, constants...)
Then again, my first thought comes back... since you are asking about the appropriateness of the architecture, what is it that you really want to achieve? --without knowledge of the problem you will only find generic answers as this one.
The usual object oriented way would be to have (pure) virtual functions in the base class that are called in operate() and that get overridden in the derived classes to execute code specific to that derived class.
Your problem is that you want to decide what to do based on more than one object's type. Virtual functions do this for one object (the one left of the . or ->) only. Doing so for more than one object is called multiple dispatch (for two objects it's also called double dispatch), and in C++ there's no built-in feature to deal with this.
Look at double dispatch, especially as done in the visitor pattern.
I have this pimpl design where the implementation classes are polymorphic but the interfaces are supposed to just contain a pointer, making them polymorphic somewhat defeats the purpose of the design.
So I create my Impl and Intf base classes to provide reference counting. And then the user can create their implementations. An example:
class Impl {
mutable int _ref;
public:
Impl() : _ref(0) {}
virtual ~Impl() {}
int addRef() const { return ++_ref; }
int decRef() const { return --_ref; }
};
template <typename TImpl>
class Intf {
TImpl* impl;
public:
Intf(TImpl* t = 0) : impl(0) {}
Intf(const Intf& other) : impl(other.impl) { if (impl) impl->addRef(); }
Intf& operator=(const Intf& other) {
if (other.impl) other.impl->addRef();
if (impl && impl->decRef() <= 0) delete impl;
impl = other.impl;
}
~Intf() { if (impl && impl->decRef() <= 0) delete impl; }
protected:
TImpl* GetImpl() const { return impl; }
void SetImpl(... //etc
};
class ShapeImpl : public Impl {
public:
virtual void draw() = 0;
};
class Shape : public Intf<ShapeImpl> {
public:
Shape(ShapeImpl* i) : Intf<ShapeImpl>(i) {}
void draw() {
ShapeImpl* i = GetImpl();
if (i) i->draw();
}
};
class TriangleImpl : public ShapeImpl {
public:
void draw();
};
class PolygonImpl : public ShapeImpl {
public:
void draw();
void addSegment(Point a, Point b);
};
Here is where have the issue. There are two possible declaration for class Polygon:
class Polygon1 : public Intf<PolygonImpl> {
public:
void draw() {
PolygonImpl* i = GetImpl();
if (i) i->draw();
}
void addSegment(Point a, Point b) {
PolygonImpl* i = GetImpl();
if (i) i->addSegment(a,b);
}
};
class Polygon2 : public Shape {
void addSegment(Point a, Point b) {
ShapeImpl* i = GetImpl();
if (i) dynamic_cast<Polygon*>(i)->addSegment(a,b);
}
}
In the Polygon1, I have rewrite the code for draw because I have not inherited it. In Polygon2 I need ugly dynamic casts because GetImpl() doesn't know about PolygonImpl. What I would like to do is something like this:
template <typename TImpl>
struct Shape_Interface {
void draw() {
TImpl* i = GetImpl();
if (i) i->draw();
}
};
template <typename TImpl>
struct Polygon_Interface : public Shape_Interface<Timpl> {
void addSegment(Point a, Point b) { ... }
};
class Shape : public TIntf<ShapeImpl>, public Shape_Interface<ShapeImpl> {...};
class Polygon : public TIntf<PolygonImpl>, public Polygon_Interface<PolygonImpl> {
public:
Polygon(PolygonImpl* i) : TIntf<PolygonImpl>(i) {}
};
But of course there's a problem here. I can't access GetImpl() from the Interface classes unless I derive them from Intf. And if I do that, I need to make Intf virtual everywhere it appears.
template <typename TImpl>
class PolygonInterface : public virtual Intf<TImpl> { ... };
class Polygon : public virtual Intf<PolygonImpl>, public PolygonInterface { ... }
OR I can store a TImpl*& in each Interface and construct them with a reference to the base Intf::impl. But that just means I have a pointer pointing back into myself for every interface included.
template <typename TImpl>
class PolygonInterface {
TImpl*& impl;
public:
PolygonInterface(TImpl*& i) : impl(i) {}
...};
Both of these solutions bloat the Intf class, add an extra dereference, and basically provide no benefit over straight polymorphism.
So, the question is, is there a third way, that I've missed that would solve this issue besides just duplicating the code everywhere (with its maintenance issues)?
TOTALLY SHOULD, BUT DOESN'T WORK: I wish there were base classes unions that just overlaid the class layouts and, for polymorphic classes, required that they have the exact same vtable layout. Then both Intf and ShapeInterface would each declare a single T* element and access it identically:
class Shape : public union Intf<ShapeImpl>, public union ShapeInterface<ShapeImpl> {};
I should note that your Impl class is nothing more than the reimplementation of a shared_ptr without the thread safety and all those cast bonuses.
Pimpl is nothing but a technic to avoid needless compile-time dependencies.
You do not need to actually know how a class is implemented to inherit from it. It would defeat the purpose of encapsulation (though your compiler does...).
So... I think that you are not trying to use Pimpl here. I would rather think this is a kind of Proxy patterns, since apparently:
Polygon1 numberOne;
Polygon2 numberTwo = numberOne;
numberTwo.changeData(); // affects data from numberOne too
// since they point to the same pointer!!
If you want to hide implementation details
Use Pimpl, but the real one, it means copying in depth during copy construction and assignment rather than just passing the pointer around (whether ref-counted or not, though ref-counted is preferable of course :) ).
If you want a proxy class
Just use a plain shared_ptr.
For inheritance
It does not matter, when you inherit from a class, how its private members are implemented. So just inherit from it.
If you want to add some new private members (usual case), then:
struct DerivedImpl;
class Derived: public Base // Base implemented with a Pimpl
{
public:
private:
std::shared_ptr<DerivedImpl> _data;
};
There is not much difference with classic implementation, as you can see, just that there is a pointer in lieu of a bunch of data.
BEWARE
If you forward declare DerivedImpl (which is the goal of Pimpl), then the destructor automatically generated by the compiler is... wrong.
The problem is that in order to generate the code for the destructor, the compiler needs the definition of DerivedImpl (ie: a complete type) in order to know how to destroy it, since a call to delete is hidden in the bowels of shared_ptr. However it may only generate a warning at compilation time (but you'll have a memory leak).
Furthermore, if you want an in-depth copy (rather than a shallow one, which consists in the copy and the original both pointing to the same DerivedImpl instance), you will also have to define manually the copy-constructor AND the assignment operator.
You may decide to create a better class that shared_ptr which will have deep-copy semantics (which could be called member_ptr as in cryptopp, or just Pimpl ;) ). This introduce a subtle bug though: while the code generated for the copy-constructor and the assignement operator could be thought of as correct, they are not, since once again you need a complete type (and thus the definition of DerivedImpl), so you will have to write them manually.
This is painful... and I'm sorry for you.
EDIT: Let's have a Shape discussion.
// Shape.h
namespace detail { class ShapeImpl; }
class Shape
{
public:
virtual void draw(Board& ioBoard) const = 0;
private:
detail::ShapeImpl* m_impl;
}; // class Shape
// Rectangle.h
namespace detail { class RectangleImpl; }
class Rectangle: public Shape
{
public:
virtual void draw(Board& ioBoard) const;
size_t getWidth() const;
size_t getHeight() const;
private:
detail::RectangleImpl* m_impl;
}; // class Rectangle
// Circle.h
namespace detail { class CircleImpl; }
class Circle: public Shape
{
public:
virtual void draw(Board& ioBoard) const;
size_t getDiameter() const;
private:
detail::CircleImpl* m_impl;
}; // class Circle
You see: neither Circle nor Rectangle care if Shape uses Pimpl or not, as its name implies, Pimpl is an implementation detail, something private that is not shared with the descendants of the class.
And as I explained, both Circle and Rectangle use Pimpl too, each with their own 'implementation class' (which can be nothing more than a simple struct with no method by the way).
I think you were right in that I didn't understand your question initially.
I think you're trying to force a square shape into a round hole... it don't quite fit C++.
You can force that your container holds pointers to objects of a given base-layout, and then allow objects of arbitrary composition to be actually pointed to from there, assuming that you as a programmer only actually place objects that in fact have identical memory layouts (member-data - there's no such thing as member-function-layout for a class unless it has virtuals, which you wish to avoid).
std::vector< boost::shared_ptr<IShape> > shapes;
NOTE at the absolute MINIMUM, you must still have a virtual destructor defined in IShape, or object deletion is going to fail miserably
And you could have classes which all take a pointer to a common implementation core, so that all compositions can be initialized with the element that they share (or it could be done statically as a template via pointer - the shared data).
But the thing is, if I try to create an example, I fall flat the second I try to consider: what is the data shared by all shapes? I suppose you could have a vector of Points, which then could be as large or small as any shape required. But even so, Draw() is truly polymorphic, it isn't an implementation that can possibly be shared by multiple types - it has to be customized for various classifications of shapes. i.e. a circle and a polygon cannot possibly share the same Draw(). And without a vtable (or some other dynamic function pointer construct), you cannot vary the function called from some common implementation or client.
Your first set of code is full of confusing constructs. Maybe you can add a new, simplified example that PURELY shows - in a more realistic way - what you're trying to do (and ignore the fact that C++ doesn't have the mechanics you want - just demonstrate what your mechanic should look like).
To my mind, I just don't get the actual practical application, unless you're tyring to do something like the following:
Take a COM class, which inherits from two other COM Interfaces:
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser
{
...
};
And now I have a diamond inheritence pattern: IShellBrowser inherits ultimately from IUnknown, as does ICommDlgBrowser. But it seems incredibly silly to have to write my own IUnknown:AddRef and IUnknown::Release implementation, which is a highly standard implementation, because there's no way to cause the compiler to let another inherited class supply the missing virtual functions for IShellBrowser and/or ICommDlgBrowser.
i.e., I end up having to:
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++m_refcount; }
virtual ULONG STDMETHODCALLTYPE Release(void) { return --m_refcount; }
...
}
because there's no way I know of to "inherit" or "inject" those function implementations into MyShellBrowserDialog from anywhere else which actually fill-in the needed virtual member function for either IShellBrowser or ICommDlgBrowser.
I can, if the implementations were more complex, manually link up the vtable to an inherited implementor if I wished:
class IUnknownMixin
{
ULONG m_refcount;
protected:
IUnknonwMixin() : m_refcount(0) {}
ULONG AddRef(void) { return ++m_refcount; } // NOTE: not virutal
ULONG Release(void) { return --m_refcount; } // NOTE: not virutal
};
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser, private IUnknownMixin
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return IUnknownMixin::AddRef(); }
virtual ULONG STDMETHODCALLTYPE Release(void) { return IUnknownMixin::Release(); }
...
}
And if I needed the mix-in to actually refer to the most-derived class to interact with it, I could add a template parameter to IUnknownMixin, to give it access to myself.
But what common elements could my class have or benefit by that IUnknownMixin couldn't itself supply?
What common elements could any composite class have that various mixins would want to have access to, which they needed to derive from themselves? Just have the mixins take a type parameter and access that. If its instance data in the most derived, then you have something like:
template <class T>
class IUnknownMixin
{
T & const m_outter;
protected:
IUnknonwMixin(T & outter) : m_outter(outter) {}
// note: T must have a member m_refcount
ULONG AddRef(void) { return ++m_outter.m_refcount; } // NOTE: not virtual
ULONG Release(void) { return --m_outter.m_refcount; } // NOTE: not virtual
};
Ultimately your question remains somewhat confusing to me. Perhaps you could create that example that shows your preferred-natural-syntax that accomplishes something clearly, as I just don't see that in your initial post, and I can't seem to sleuth it out from toying with these ideas myself.
I have seen lots of solutions to this basic conundrum: polymorphism + variation in interfaces.
One basic approach is to provide a way to query for extended interfaces - so you have something along the lines of COM programming under Windows:
const unsigned IType_IShape = 1;
class IShape
{
public:
virtual ~IShape() {} // ensure all subclasses are destroyed polymorphically!
virtual bool isa(unsigned type) const { return type == IType_IShape; }
virtual void Draw() = 0;
virtual void Erase() = 0;
virtual void GetBounds(std::pair<Point> & bounds) const = 0;
};
const unsigned IType_ISegmentedShape = 2;
class ISegmentedShape : public IShape
{
public:
virtual bool isa(unsigned type) const { return type == IType_ISegmentedShape || IShape::isa(type); }
virtual void AddSegment(const Point & a, const Point & b) = 0;
virtual unsigned GetSegmentCount() const = 0;
};
class Line : public IShape
{
public:
Line(std::pair<Point> extent) : extent(extent) { }
virtual void Draw();
virtual void Erase();
virtual void GetBounds(std::pair<Point> & bounds);
private:
std::pair<Point> extent;
};
class Polygon : public ISegmentedShape
{
public:
virtual void Draw();
virtual void Erase();
virtual void GetBounds(std::pair<Point> & bounds);
virtual void AddSegment(const Point & a, const Point & b);
virtual unsigned GetSegmentCount() const { return vertices.size(); }
private:
std::vector<Point> vertices;
};
Another option would be to make a single richer base interface class - which has all the interfaces you need, and then to simply define a default, no-op implementation for those in the base class, which returns false or throws to indicate that it isn't supported by the subclass in question (else the subclass would have provided a functional implementation for this member function).
class Shape
{
public:
struct Unsupported
{
Unsupported(const std::string & operation) : bad_op(operation) {}
const std::string & AsString() const { return bad_op; }
std::string bad_op;
};
virtual ~Shape() {} // ensure all subclasses are destroyed polymorphically!
virtual void Draw() = 0;
virtual void Erase() = 0;
virtual void GetBounds(std::pair<Point> & bounds) const = 0;
virtual void AddSegment(const Point & a, const Point & b) { throw Unsupported("AddSegment"); }
virtual unsigned GetSegmentCount() const { throw Unsupported("GetSegmentCount"); }
};
I hope that this helps you to see some possibilities.
Smalltalk had the wonderful attribute of being able to ask the meta-type-system whether a given instance supported a particular method - and it supported having a class-handler that could execute anytime a given instance was told to perform an operation it didn't support - along with what operation that was, so you could forward it as a proxy, or you could throw a different error, or simply quietly ignore that operation as a no-op).
Objective-C supports all of those same modalities as Smalltalk! Very, very cool things can be accomplished by having access to the type-system at runtime. I assume that .NET can pull of some crazy cool stuff along those lines (though I doubt that its nearly as elegant as Smalltalk or Objective-C, from what I've seen).
Anyway, ... good luck :)
In a C++ physics simulation, I have a class called Circle, and Square. These are Shapes, and have a method called push(), which applies force to it. There is then a special case of Circle, call it SpecialCircle, in which push() should exhibit slightly different properties. But in fact, there is also SpecialSquare() which should exhibit the same force properties. So I'd like to have an abstract base class called Shape which takes care of Circles and Squares, but then I'd also like an abstract base class called Special, which applies special properties to force().
What's the best way to design this class structure?
So far, I've got:
class Shape {
virtual void push();
};
class Circle : public Shape {};
class Square : public Shape {};
class Special {
virtual void push();
};
class SpecialCircle : public Circle, Special {};
class SpecialSquare : public Square, Special {};
Of course, the above won't compile, since Special::push() and Shape::push() conflict. I get "error: request for member ‘push’ is ambiguous", as expected.
How can I re-organize my class structure so that Circle and Square can share certain properties with each other, but SpecialCircle and SpecialSquare can still inherit from Shape, and also inherit modified functionality from Special?
Thanks.
ps., is this the diamond inheritance problem?
Another solution (it may or may not fit your needs, it depends on the details of your implementation):
Have the class Behavior, and let NormalBehavior and SpecialBehavior inherit from it.
Have the class Shape, and let Square and Circle inherit from it. Let Shape be an aggregate type, with a Behavior member (i.e. you pass a Behavior object to the various Shape constructors). In other words, let a Shape have a Behavior.
Delegate the actual differences in the behavior of shapes to methods of the Behavior hierarchy.
Conversely, you can:
Have the class PhysicalObject, and let NormalObject and SpecialObject inherit from it;
Have the class Shape, and let Square and Circle inherit from it;
Let a PhysicalObject have a Shape.
Prefer aggregation over inheritance. This is an application of the Bridge pattern. The advantage of this strategy with respect to having Square, SpecialSquare, Circle, and SpecialCircle, is that tomorrow you'll have to add Rectangle, Hexagon and so on, and for each shape you add you'll have to implement two classes (duplicated code is evil); this is, in my opinion, the real issue that Bridge addresses.
It's said that every problem in software can be solved by adding an additional layer of indirection.
Herb Sutter has an excellent article on how to solve your problem: Multiple Inheritance - Part III
In short, you use intermediate classes to 'rename' the virtual functions. As Herb says:
Renaming Virtual Functions
If the two inherited functions had different signatures, there would be no problem: We would just override them independently as usual. The trick, then, is to somehow change the signature of at least one of the two inherited functions.
The way to change a base class function's signature is to create an intermediate class which derives from the base class, declares a new virtual function, and overrides the inherited version to call the new function
Here's a long example using your classes:
class Shape {
public:
virtual void push() = 0;
};
class Circle : public Shape
{
public:
void push() {
printf( "Circle::push()\n");
}
};
class Square : public Shape
{
public:
void push() {
printf( "Square::push()\n");
}
};
class Special {
public:
virtual void push() = 0;
};
class Circle2: public Circle
{
public:
virtual void pushCircle() = 0;
void push() {
pushCircle();
}
};
class Square2: public Square
{
public:
virtual void pushSquare() = 0;
void push() {
pushSquare();
}
};
class Special2 : public Special
{
public:
virtual void pushSpecial() = 0;
void push() {
pushSpecial();
}
};
class SpecialCircle : public Circle2, public Special2
{
public:
void pushSpecial() {
printf( "SpecialCircle::pushSpecial()\n");
}
void pushCircle() {
printf( "SpecialCircle::pushCircle()\n");
}
};
class SpecialSquare : public Square2, public Special2
{
public:
void pushSpecial() {
printf( "SpecialSquare::pushSpecial()\n");
}
void pushSquare() {
printf( "SpecialSquare::pushSquare()\n");
}
};
int main( int argc, char* argv[])
{
SpecialCircle sc;
SpecialSquare ss;
// sc.push(); // can't be called - ambiguous
// ss.push();
sc.pushCircle();
ss.pushSquare();
Circle* pCircle = ≻
pCircle->push();
Square* pSquare = &ss;
pSquare->push();
Special* pSpecial = ≻
pSpecial->push();
pSpecial = &ss;
pSpecial->push();
return 0;
}
Rather than thinking of code reuse through inheritance, the use of mixins will give you the code reuse you want without the problems of multiple inheritance.
If you are unfamiliar with the technique, do a search on SO or Google. Make sure you search for both "mixin" and "Curiously Recurring Template Pattern". There are heaps of great articles around to get you started.
When you have to inherit from multiple interfaces with the same method the compiler can't tell which one are you trying to call, you can fix this by overriding such method and call the one you want.
class SpecialCircle : public Circle, Special {
public:
virtual void push() { Special::push(); }
};
class SpecialSquare : public Square, Special {
public:
virtual void push() { Special::push(); }
};
But in this case I think the correct OO approach is to factor out the push behavior in its own class, like Federico Ramponi have suggested.
Have a SpecialShape from Shape and SpecialCircle and SpecialSquare from SpecialShape.
Well, if the special and normal circles can be both applied forces to, and the special circle has another method that applies special forces, why not have two interfaces and two methods?
struct Applicable {
virtual ~Applicable() { }
// if it applies force, better be explicit with naming it.
virtual void applyForce() = 0;
};
struct SpecialApplicable {
virtual ~SpecialApplicable() { }
virtual void applySpecialForce() = 0;
};
struct Shape {
virtual ~Shape() { }
Size getSize();
Point getPosition();
// ...
};
struct Circle : Shape, Applicable {
virtual void applyForce() { /* ... */ }
}
struct SpecialCircle : Circle, SpecialApplicable {
virtual void applySpecialForce() { /* .... */ }
};
If it doesn't make sense if there is both a special and a normal apply method (which the name of the class - SpecialCircle - suggests), then why not do even this:
struct Circle : Shape, Applicable {
virtual void applyForce() { /* ... */ }
}
struct SpecialCircle : Circle {
// applies force, but specially
virtual void applyForce() { /* .... */ }
};
You can also put the applyForce into the Shape class. It also depends on the environment in which those classes are used. What, in any case, you really should avoid is having the same method in two base classes that appear in two difference base-lattices. Because that inevitable will lead to such ambiguity problems. The diamond inheritance is when you use virtual inheritance. I believe there are other good answers on stackoverflow explaining that. It isn't applicable for your problem, because the ambiguity arises because the method appears in two base class sub-objects of different types. (It only solves such cases where the base classes have the same type. In those cases, it will merge the base classes and there will only be one base class sub-object contained - inherited by virtual inheritance)
OK, I have a somewhat complicated system in C++. In a nutshell, I need to add a method to a third party abstract base class. The third party also provides a ton of derived classes that also need the new functionality.
I'm using a library that provides a standard Shape interface, as well as some common shapes.
class Shape
{
public:
Shape(position);
virtual ~Shape();
virtual position GetPosition() const;
virtual void SetPosition(position);
virtual double GetPerimeter() const = 0;
private: ...
};
class Square : public Shape
{
public:
Square(position, side_length);
...
};
class Circle, Rectangle, Hexagon, etc
Now, here's my problem. I want the Shape class to also include a GetArea() function. So it seems like I should just do a:
class ImprovedShape : public virtual Shape
{
virtual double GetArea() const = 0;
};
class ImprovedSquare : public Square, public ImprovedShape
{
...
}
And then I go and make an ImprovedSquare that inherits from ImprovedShape and Square. Well, as you can see, I have now created the dreaded diamond inheritance problem. This would easily be fixed if the third party library used virtual inheritance for their Square, Circle, etc. However, getting them to do that isn't a reasonable option.
So, what do you do when you need to add a little functionality to an interface defined in a library? Is there a good answer?
Thanks!
Why does this class need to derive from shape?
class ImprovedShape : public virtual Shape
{
virtual double GetArea() const = 0;
};
Why not just have
class ThingWithArea
{
virtual double GetArea() const = 0;
};
ImprovedSquare is a Shape and is a ThingWithArea
We had a very similar problem in a project and we solved it by just NOT deriving ImprovedShape from Shape. If you need Shape functionality in ImprovedShape you can dynamic_cast, knowing that your cast will always work. And the rest is just like in your example.
I suppose the facade pattern should do the trick.
Wrap the 3rd party interface into an interface of your own, and your application's code works with the wrapper interface rather than the 3rd party interface. That way you've nicely insulated changes in the uncontrolled 3rd party interface as well.
Perhaps you should read up on proper inheritance, and conclude that ImprovedShape does not need to inherit from Shape but instead can use Shape for its drawing functionality, similar to the discussion in point 21.12 on that FAQ on how a SortedList doesn't have to inherit from List even if it wants to provide the same functionality, it can simply use a List.
In a similar fashion, ImprovedShape can use a Shape to do it's Shape things.
Possibly a use for the decorator pattern? [http://en.wikipedia.org/wiki/Decorator_pattern][1]
Is it possible to do a completely different approach - using templates and meta-programming techniques? If you're not constrained to not using templates, this could provide an elegant solution. Only ImprovedShape and ImprovedSquare change:
template <typename ShapePolicy>
class ImprovedShape : public ShapePolicy
{
public:
virtual double GetArea();
ImprovedShape(void);
virtual ~ImprovedShape(void);
protected:
ShapePolicy shape;
//...
};
and the ImprovedSquare becomes:
class ImprovedSquare : public ImprovedShape<Square>
{
public:
ImprovedSquare(void);
~ImprovedSquare(void);
// ...
};
You'll avoid the diamond inheritance, getting both the inheritance from your original Shape (through the policy class) as well as the added functionality you want.
Another take on meta-programming/mixin, this time a bit influenced by traits.
It assumes that calculating area is something you want to add based on exposed properties; you could do something which kept with encapsulation, it that is a goal, rather than modularisation. But then you have to write a GetArea for every sub-type, rather than using a polymorphic one where possible. Whether that's worthwhile depends on how committed you are to encapsulation, and whether there are base classes in your library you could exploit common behaviour of, like RectangularShape below
#import <iostream>
using namespace std;
// base types
class Shape {
public:
Shape () {}
virtual ~Shape () { }
virtual void DoShapyStuff () const = 0;
};
class RectangularShape : public Shape {
public:
RectangularShape () { }
virtual double GetHeight () const = 0 ;
virtual double GetWidth () const = 0 ;
};
class Square : public RectangularShape {
public:
Square () { }
virtual void DoShapyStuff () const
{
cout << "I\'m a square." << endl;
}
virtual double GetHeight () const { return 10.0; }
virtual double GetWidth () const { return 10.0; }
};
class Rect : public RectangularShape {
public:
Rect () { }
virtual void DoShapyStuff () const
{
cout << "I\'m a rectangle." << endl;
}
virtual double GetHeight () const { return 9.0; }
virtual double GetWidth () const { return 16.0; }
};
// extension has a cast to Shape rather than extending Shape
class HasArea {
public:
virtual double GetArea () const = 0;
virtual Shape& AsShape () = 0;
virtual const Shape& AsShape () const = 0;
operator Shape& ()
{
return AsShape();
}
operator const Shape& () const
{
return AsShape();
}
};
template<class S> struct AreaOf { };
// you have to have the declaration before the ShapeWithArea
// template if you want to use polymorphic behaviour, which
// is a bit clunky
static double GetArea (const RectangularShape& shape)
{
return shape.GetWidth() * shape.GetHeight();
}
template <class S>
class ShapeWithArea : public S, public HasArea {
public:
virtual double GetArea () const
{
return ::GetArea(*this);
}
virtual Shape& AsShape () { return *this; }
virtual const Shape& AsShape () const { return *this; }
};
// don't have to write two implementations of GetArea
// as we use the GetArea for the super type
typedef ShapeWithArea<Square> ImprovedSquare;
typedef ShapeWithArea<Rect> ImprovedRect;
void Demo (const HasArea& hasArea)
{
const Shape& shape(hasArea);
shape.DoShapyStuff();
cout << "Area = " << hasArea.GetArea() << endl;
}
int main ()
{
ImprovedSquare square;
ImprovedRect rect;
Demo(square);
Demo(rect);
return 0;
}
Dave Hillier's approach is the right one. Separate GetArea() into its own interface:
class ThingWithArea
{
public:
virtual double GetArea() const = 0;
};
If the designers of Shape had done the right thing and made it a pure interface,
and the public interfaces of the concrete classes were powerful enough, you could
have instances of concrete classes as members. This is how you get SquareWithArea
(ImprovedSquare is a poor name) being a Shape and a ThingWithArea:
class SquareWithArea : public Shape, public ThingWithArea
{
public:
double GetPerimeter() const { return square.GetPerimeter(); }
double GetArea() const { /* do stuff with square */ }
private:
Square square;
};
Unfortunately, the Shape designers put some implementation into Shape, and you
would end up carrying two copies of it per SquareWithArea, just like in
the diamond you originally proposed.
This pretty much forces you into the most tightly coupled, and therefore least
desirable, solution:
class SquareWithArea : public Square, public ThingWithArea
{
};
These days, it's considered bad form to derive from concrete classes in C++.
It's hard to find a really good explanation why you shouldn't. Usually, people
cite Meyers's More Effective C++ Item 33, which points out the impossibility
of writing a decent operator=() among other things. Probably, then, you should
never do it for classes with value semantics. Another pitfall is where the
concrete class doesn't have a virtual destructor (this is why you should
never publicly derive from STL containers). Neither applies here. The poster
who condescendingly sent you to the C++ faq to learn about inheritance is
wrong - adding GetArea() does not violate Liskov substitutability. About
the only risk I can see comes from overriding virtual functions in the
concrete classes, when the implementer later changes the name and silently breaks
your code.
In summary, I think you can derive from Square with a clear conscience.
(As a consolation, you won't have to write all the forwarding functions for
the Shape interface).
Now for the problem of functions which need both interfaces. I don't like
unnecessary dynamic_casts. Instead, make the function take references to
both interfaces and pass references to the same object for both at the call site:
void PrintPerimeterAndArea(const Shape& s, const ThingWithArea& a)
{
cout << s.GetPerimeter() << endl;
cout << a.GetArea() << endl;
}
// ...
SquareWithArea swa;
PrintPerimeterAndArea(swa, swa);
All PrintPerimeterAndArea() needs to do its job is a source of perimeter and a
source of area. It is not its concern that these happen to be implemented
as member functions on the same object instance. Conceivably, the area could
be supplied by some numerical integration engine between it and the Shape.
This gets us to the only case where I would consider passing in one reference
and getting the other by dynamic_cast - where it's important that the two
references are to the same object instance. Here's a very contrived example:
void hardcopy(const Shape& s, const ThingWithArea& a)
{
Printer p;
if (p.HasEnoughInk(a.GetArea()))
{
s.print(p);
}
}
Even then, I would probably prefer to send in two references rather than
dynamic_cast. I would rely on a sane overall system design to eliminate the
possibility of bits of two different instances being fed to functions like this.
GetArea() need not be a member. It could be templated function, so that you can invoke it for any Shape.
Something like:
template <class ShapeType, class AreaFunctor>
int GetArea(const ShapeType& shape, AreaFunctor func);
The STL min, max functions can be thought of as an analogy for your case. You can find a min and max for an array/vector of objects given a comparator function. Like wise, you can derive the area of any given shape provided the function to compute the area.
There exists a solution to your problem, as I understood the question. Use the addapter-pattern. The adapter pattern is used to add functionality to a specific class or to exchange particular behaviour (i.e. methods). Considering the scenario you painted:
class ShapeWithArea : public Shape
{
protected:
Shape* shape_;
public:
virtual ~ShapeWithArea();
virtual position GetPosition() const { return shape_->GetPosition(); }
virtual void SetPosition(position) { shape_->SetPosition(); }
virtual double GetPerimeter() const { return shape_->GetPerimeter(); }
ShapeWithArea (Shape* shape) : shape_(shape) {}
virtual double getArea (void) const = 0;
};
The Adapter-Pattern is meant to adapt the behaviour or functionality of a class. You can use it to
change the behaviour of a class, by not forwarding but reimplementing methods.
add behaviour to a class, by adding methods.
How does it change behaviour? When you supply an object of type base to a method, you can also supply the adapted class. The object will behave as you instructed it to, the actor on the object will only care about the interface of the base class. You can apply this adaptor to any derivate of Shape.