Virtual inheritance constructor arguments - c++

I know that virtual inheritance enters into the realm of "perhaps you should be doing something different," but I sometimes it is unavoidable. I am a little confused about the preferred way to handle constructor arguments when using virtual inheritance to solve some sort of diamond problem.
Here is a very simple example to help me demonstrate:
#include <iostream>
class Ball {
public:
auto diameter() const { return _diameter; }
protected:
Ball(unsigned int diameter): _diameter(diameter) {}
private:
unsigned int _diameter;
};
class ColoredBall : virtual public Ball {
public:
enum class Color {
RED,
GREEN,
BLUE
};
auto color() const { return _color; }
protected:
ColoredBall(unsigned int diameter, Color color):
Ball(diameter),
_color(color)
{
}
private:
Color _color;
};
std::ostream& operator<<(std::ostream& os, const ColoredBall::Color& v) {
switch(v) {
case ColoredBall::Color::RED:
os << "RED";
break;
case ColoredBall::Color::GREEN:
os << "GREEN";
break;
case ColoredBall::Color::BLUE:
os << "BLUE";
break;
}
return os;
}
class BouncyBall : virtual public Ball {
public:
auto bounciness() const { return _bounciness; }
protected:
BouncyBall(unsigned int diameter, double bounciness):
Ball(diameter),
_bounciness(bounciness)
{
}
private:
double _bounciness;
};
class MyBall : public ColoredBall, public BouncyBall {
public:
MyBall():
Ball(10),
ColoredBall(20, Color::GREEN),
BouncyBall(30, 5.5)
{
}
};
int main() {
MyBall b;
std::cout << "b.diameter() = " << b.diameter() << std::endl;
std::cout << "b.color() = " << b.color() << std::endl;
std::cout << "b.bounciness() = " << b.bounciness() << std::endl;
return 0;
}
My base class Ball's constructor requires a single argument used to initialize a member variable diameter. Thus, every Ball subclass, has a diameter variable (yes, I know this could be accomplished using virtual method as well).
Next I have two subclasses of Ball (ColoredBall and BouncyBall) which both add their own member variables (they may also add some more features). Here is where my confusion starts. Since, for example, ColoredBall "is a" Ball, in order for its constructor to be complete, it must call the (non-default) constructor of Ball and thus must provide a diameter. So, it seems logical make this an argument of ColoredBall's constructor as well and "forward" this along to Ball's constructor. The same applies for BouncyBall.
Here's the "weirdness." If I now create a subclass MyBall which is both a ColoredBall and a BouncyBall, I need to explicitly call the constructor of Ball because Ball has been inherited virtually in both ColoredBall and BouncyBall. It is this explicit call that really initializes the Ball class. This means that, even though I have to pass the diameter parameter to both the ColoredBall and BouncyBall constructors, it is not used at all. This means (as I show in my example), I could pass completely different values to these constructors and only the one passed explicitly to Ball will really matter.
While I understand why this happens, I am wondering if there is a better way to handle/express this?
EDIT
As an aside, for those familiar with Qt, I have this problem crop up quite a few times when dealing with QObjects. Sometimes, I want to create a few interfaces (e.g., classes A and B) that rely on the Qt meta-object system, thus I inherit from QObject. However, what if I want to create a class that inherits from both of these interfaces (e.e., class C), this is impossible.

Related

C++ polymorphism: how to create derived class objects

I have an abstract base class called BaseStrategy. It contains one pure virtual function calculateEfficiency(). There are two classes ConvolutionStrategy and MaxPoolStrategy which derive from this base class and implement their own specific version of calculateEfficiency().
Here is some code:
class BaseStrategy {
public:
explicit BaseStrategy();
virtual ~BaseStrategy() = default;
private:
virtual double calculateEfficiency(mlir::Operation* op) = 0;
};
class ConvolutionStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for convolution
return 1;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for MaxPool
return 1;
}
};
Now I have another class called StrategyAssigner. It has method calculateAllLayerEfficiencies() whose purpose is to iterate over all layers in a network. Depending on the type of layer there is a switch statement and should call the correct calculateEfficiency() depending on the layer type.
class StrategyAssigner final {
public:
explicit StrategyAssigner(){};
public:
void calculateAllLayerEfficiencies() {
// Logic to iterate over all layers in
// a network
switch (layerType) {
case Convolution:
// Call calculateEfficiency() for Convolution
break;
case MaxPool:
// Call calculateEfficiency() for MaxPool
break;
}
};
}
int main ()
{
StrategyAssigner assigner;
assigner.calculateAllLayerEfficiencies();
}
My question is, should I store references of objects Convolution and MaxPool in the class StrategyAssigner so that I can call the respective calculateEfficiency().
Or could you suggest a better way to call calculateEfficiency(). I don't really know how to create the objects (stupid as that sounds).
I can't make calculateEfficiency() static as I need them to be virtual so that each derived class can implemented its own formula.
If you included complete code I could give a more detailed answer, but you need to store BaseStrategy pointers that are initialized with derived class instances. Here's an example made from some of your code:
std::vector<std::unique_ptr<BaseStrategy>> strategies;
strategies.emplace_back(new ConvolutionStrategy);
strategies.emplace_back(new MaxPoolStrategy);
for (int i = 0; i < strategies.size(); ++i) {
std::unique_ptr<BaseStrategy>& pStrat = strategies[i];
pStrat->calculateEfficiency(...);
}
Note that this won't compile because I don't have enough details from the code you posted to make it so, but this shows how to exploit polymorphism in the way that you need.
Also, I used smart pointers for memory management; use these at your discretion.
You can indeed use runtime polymorphism here:
Declare ~BaseStrategy virtual (you are already doing it ;-)
If you are never going to instantiate a BaseStrategy, declare one of its methods as virtual pure, e.g. calculateEfficiency (you are already doing it as well!). I would make that method const, since it doesn't look it's going to modify the instance. And it will need to be public, because it will need to be accessed from StrategyAnalyser.
Declare calculateEfficiency as virtual and override in each of the subclasses. It could also be final if you don't want subclasses to override it.
I'd keep a std::vector of smart pointers to BaseStrategy at StrategyAssigner. You can use unique_ptrs if you think this class is not going to be sharing those pointers.
The key point now is that you create heap instances of the subclasses and assign them to a pointer of the base class.
class StrategyAssigner final {
public:
void addStrategy(std::unique_ptr<BaseStrategy> s) {
strategies_.push_back(std::move(s));
}
private:
std::vector<std::unique_ptr<BaseStrategy>> strategies_{};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
}
Then, when you call calculateEfficiency using any of those pointers to BaseStrategy, the runtime polymorphism will kick in and it will be the method for the subclass the one that will be actually called.
class ConvolutionStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "ConvolutionStrategy::calculateEfficiency()\n";
return 10;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "MaxPoolStrategy::calculateEfficiency()\n";
return 20;
}
};
class StrategyAssigner final {
public:
void calculateAllLayerEfficiencies() {
auto sum = std::accumulate(std::cbegin(strategies_), std::cend(strategies_), 0,
[](auto total, const auto& strategy_up) {
return total + strategy_up->calculateEfficiency(); });
std::cout << "Sum of all efficiencies: " << sum << "\n";
};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
assigner.addStrategy(std::make_unique<MaxPoolStrategy>());
assigner.calculateAllLayerEfficiencies();
}
// Outputs:
//
// ConvolutionStrategy::calculateEfficiency()
// MaxPoolStrategy::calculateEfficiency()
// Sum of all efficiencies: 30
[Demo]

How to construct a template class type that can be substituted for subclasses and then called generically?

I have 10 Coin types: BTC, ETH, Shift etc. For this I have a superclass "Coin" and subclasses for each of those coins. Then I have a pointer to a "Coin" type, so that I can call each of the subclasses no matter what subtype they are.
Problem is, I only know how to do this in Java and not in C++. I have a hard time searching for the correct terms, because I don't really know what to search for other than "generics". What I want is something like this:
// Superclass
class Coin {
public:
virtual void handleCoin();
};
// Subclass
class BTC: public Coin {
void handleCoin();
}
BTC::BTC() = default;
BTC::~BTC() = default;
BTC::handleCoin() {
std::cout << "handling BTC" << std::endl;
}
// Subclass
class ETH: public Coin {
void handleCoin();
}
ETH::ETH() = default;
ETH::~ETH() = default;
ETH::handleCoin() {
std::cout << "handling ETH" << std::endl;
}
// Execute
int main() {
Coin* coin;
coin = BTC();
coin.handleCoin();
coin = ETH();
coin.handleCoin();
return 0;
}
I want this to print:
handling BTC
handling ETH
I know I need to work with templates, but I cannot find a specific example of this specific case.
Also, my constructors don't take arguments, so I guess my template declaration would be something like
template<>
Yet all the examples I see work with
template<typename T>
and then use type T as function arguments like calling
max<float, float>
max<double, double>
But that's not what I'm looking for. Is there a way to translate this example above to working C++ code?
From the code posted I don't see a need for templates, virtual methods work without templates. To fix your code in main you need to use pointers/references and also have a virtual destructor.
class Coin {
public:
virtual void handleCoin();
virtual ~Coin()=default;
};
class BTC: public Coin {
public:
BTC::BTC() = default;
//Destructor of a derived class is automatically virtual if the base class's one is.
void handleCoin();
}
// Subclass
class ETH: public Coin {
void handleCoin();
ETH::ETH() = default;
//Still virtual even if you specify otherwise
ETH::~ETH() = default;
}
int main() {
Coin* coin;
coin = new BTC();//Returns BTC* <--pointer
coin->handleCoin();
delete coin;//Calls Coin::~Coin() -> thus the need for virtual so BTC::~BTC is called instead.
coin = new ETH();
coin->handleCoin();
delete coin;//Same, calls ETH::~ETH()
return 0;
}
Manual memory management is error-prone, from C++11 there's a better approach which should be strongly preferred:
int main() {
std::unique_ptr<Coin> coin;//Hides the pointer, but still has pointer-like semantics
coin = std::make_unique<BTC>();
coin->handleCoin();
//Automatically frees old memory
coin = std::make_unique<BTC>();
coin->handleCoin();
//Calls unique ptr's dtor because coin is local variable, which again frees the memory correctly.
return 0;
}

How can I insert a Parent* object (which points to an &Child object), into a vector<Child>? [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 8 years ago.
I've provided an extremely simplified version of the code which reproduces the error.
class Shape {
public:
virtual void func()=0;
};
class Circle : public Shape {
public:
Circle() { }
void func() { }
};
class Square : public Shape {
public:
Square() { }
void func() { }
};
int main() {
Circle c;
std::vector<Circle> circs;
std::vector<Shape*> shapes;
shapes.push_back(&c);
circs.push_back(shapes[0]); //ie, the Circle object that was just pushed into the 'shapes' vector.
}
I know that as of right now, this is functionally useless, and that I could just push the Circle object to the vector - however, in keeping with the shape analogy, my project also has triangles, squares, etc. I process data using a function which accepts Shape& as a parameter, so that I can send all shapes to one function, instead of separate functions for each shape. That's besides the point, but gives insight into why I'm doing what I'm doing in the simplified code.
The last line in this code will not work. Could anyone tell me why? Or provide me with a solution/work-around? Is this considered bad programming-style?
EDIT: So I've solved the Object Slicing issue I was having. For anyone with the same issue, look at fgp's answer in the following thread:
What is object slicing?
I used the following to help allow what I was trying to do (Move a Circle object to a Shape*, compute some things, then push the Circle (which is in the Shape* vector), to its final resting place, a Circle vector:
class Shape {
public:
virtual Shape& operator=(const Shape& s) {
assign(s);
return *this;
}
virtual std::string getName() = 0;
virtual int getEdges() = 0;
protected:
std::string name;
int edges;
void assign(const Shape& s) {
this->name = s.name;
this->edges = s.edges;
}
};
class Circle : public Shape {
private:
int radius;
public:
Circle() { name = "Circle"; edges = 1; }
Circle(int rad) { name = "Circle"; edges = 1; radius = rad; }
virtual Circle& operator=(const Shape& s) {
if (const Circle* c = dynamic_cast<const Circle*>(&s))
assign(*c);
else{
std::cout << "BAD ASSIGNMENT IN CIRCLE.";
//THROW ERROR HERE INSTEAD OF THE ABOVE COUT
}
return *this;
}
std::string getName() { return name; }
int getEdges() { return edges; }
int getRadius() { return radius; }
void setRadius(int r) { radius = r; }
protected:
void assign(const Circle& c) {
Shape::assign(c);
this->radius = c.radius;
}
};
int main() {
std::vector<Shape*> shapes;
std::vector<Circle> circs;
Circle c2(5); //Creates a circle with 5 for the radius.
shapes.push_back(&c2); //Pushing the 5-radius circle into the Shapes* vector
Circle c3; //Creates a circle with default constructor (which does NOT define radius)
c3 = *shapes[0]; //Now, the overloaded assignment operator. Look at Circle::assign(const Shape&) function
circs.push_back(c3); //We push our newly assigned circle to our Circle vector
std::cout << "c3 radius: " << circs[0].getRadius(); //This will be 5!
}
It was a pleasant surprise to see this work! c3 will now know about c2's radius, showing that the overloaded assignment operators work for a Shape->Circle conversion.
If anyone has some suggestions, please let me know!
(I will be creating a Circle constructor that takes a (const Shape&) param, so I can use Circle c = *shapes[0], instead of having to separate the lines since it cannot find a constructor that accepts that parameter).
EDIT2: Also, if you use this, make sure you throw an error (I left a comment where you should).
This in general is a bad idea to do such things to down cast like you want. However to directly answer the question:
Circle* t = dynamic_cast<Circle*>(shapes[0]);
if(t) //make sure dynamic cast succeeded
circs.push_back(*t);
You have to cast the reference to a Circle type, because it was a Shape.
As I mentioned before, this is not ideal. What you should really do is allow your code to work on polymorphic principles. Use the abstract base class to your advantage! Otherwise this could lead to undefined behavior, especially when shapes probably stores more than just Circles in more realistic code.
Although a class is derived from another one, they're still two different types and thus creating a vector of base objects is different from a vector of derived objects.
As a design point of view (and I strongly reccommend it) you can store a vector of pointers to the base class and let the virtual polymorphism do its job: use a vector of pointers to the base class instead of references.
Edit: since you asked me to expand a bit more on the design concept, this is what I had in mind:
#include <iostream>
#include <vector>
using namespace std;
class Shape {
protected:
Shape() {} // Having a protected constructor only allows you to
// call it from the same or derived class
public:
virtual void func()=0;
};
class Circle : public Shape {
public:
Circle() { }
void func() { cout << "Hello from a Circle object" << endl; }
};
class Square : public Shape {
public:
Square() { }
void func() { cout << "Hello from a Square object" << endl; }
};
int main() {
std::vector<Shape*> shapes;
Circle c;
Square s;
shapes.push_back(&c); // Store the address of the object
shapes.push_back(&s); // Store the address of the object
// A call through a pointer to a virtul polymorphic class
// will make sure to call the appropriate function
shapes[0]->func(); // Hello from a circle object
shapes[1]->func(); // Hello from a square object
}
http://ideone.com/X52GLa
which is an example of runtime polymorphism where you only store a vector of base class pointers. Notice the protected constructor: it prevents you from instantiating Shape objects directly outside of the derived classes.

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.

Looking for a better way than virtual inheritance in C++

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.