This is a design issue. Remember that inheritance is a one-way relationship (for the most part). All triangles are shapes, but not all shapes are triangles. Just because you have a parent class, doesn't mean you should
always use a pointer to the parent class. If you're dealing with the child class specifically, then use the child class directly.
For example... this code you posted makes me raise an eyebrow:
1 2 3 4 5 6 7
|
class Triangle: public Shape
{
public:
static Shape* getInstance()
{
return new Triangle();
}
|
because getInstance is not only specific to Triangle, but also
static it must be explicitly invoked with the Triangle classname. IE:
shape = Triangle::getInstance();
. Yet you're returning a Shape and not a Triangle! If the object cannot be created abstractly, then it makes no sense to return an abstract pointer. This discards information prematurely. Obviously code that is calling this function knows that the object is a Triangle, so why not use a Triangle pointer?
Ex:
1 2 3 4 5 6 7 8 9
|
static Shape* getInst_Shape() // bad
{
return new Triangle();
}
static Triangle* getInst_Tri() // good
{
return new Triangle();
}
|
1 2 3 4 5 6 7 8 9
|
// I want to make a triangle and call anotherMethod()
Triangle* foo = Triangle::getInst_Tri();
foo->anotherMethod(); // easy peasy
// but if the getInstance function is needlessly abstracted, I need more work:
foo = static_cast<Triangle*>(Triangle::getInst_Shape());
foo->anotherMethod();
|
The latter bit is redundant. The cast shouldn't have to be necessary. It's already implied that the object is a triangle by the fact that I'm calling a Triangle member function.
Just because you
can make a Triangle a Shape, doesn't mean you
should.
------------------------ in that same vein...
If you're writing code that uses generic
Shape
s, then you shouldn't be calling anotherMethod because anotherMethod requires the object be a Triangle (and not any other kind of shape). Code that assumes the object is a Triangle should be using a
Triangle*
instead of a
Shape*
.
You should
not be writing code which uses abstract objects such as Shape*, but assumes they are a specific type of shape. Any code that takes a Shape* should work with
any kind of shape or else your code should be reorganized.
If you are using Shape* and discover that the shape is in fact a triangle, you should then be using a Triangle* and should no longer be using a Shape*.