I recently found an example of using static member functions in pure abstract classes to initialize pointers to objects of its derived classes.
I was wondering, if it's a design pattern or if it's a good programming practice? The code below is only an ilustration (e.g. both the defineRectangle() and defineCircle() member
functions):
class Shape;
typedef std::unique_ptr<Shape> shape_ptr;
class Shape{
public:
Shape(){};
virtual ~Shape(){};
virtual void draw() const = 0;
virtual float area() const = 0;
virtual shape_ptr clone() const = 0;
virtual shape_ptr create() const = 0;
static shape_ptr defineRectangle(int, int );
static shape_ptr defineCircle(float);
};
shape_ptr Shape::defineRectangle(int height, int width){
shape_ptr ptrRectangle = shape_ptr(new Rectangle(height, width));
return (ptrRectangle);
}
shape_ptr Shape::defineCircle(float radius){
shape_ptr ptrCircle = shape_ptr(new Circle(radius));
return (ptrCircle);
}
The final goal is to define a container of derived classes. For instance:
std::vector<std::unique_ptr<Shape> > vect;
and then we could add the derived classes in the container by either calling the static member functions of the Shape class:
vect.push_back(Shape::defineCircle(10));
vect.push_back(Shape::defineRectangle(5, 4));
or directly without any interface:
vect.push_back(std::unique_ptr<Shape>(new Circle(10)));
vect.push_back(std::unique_ptr<Shape>(new Rectangle(5,4)));
Which of both two ways of adding a derived class in a container should be preferred and why?
The full code can be found in the following link.
Any lights on it are really welcomed ;-)
I was wondering, if it's a design pattern or if it's a good programming practice?
Yes, it's a variation on the factory pattern.
Basically put, it allows you to have a single method, that depending on the arguments to that method, will dispatch the dynamic creation of the correct derived object type. This allows you to use the same "factory" function in your code, and if there are any changes or additions to the underlying objects that the factory method creates, you do not have to change the code that is actually calling your "factory" function. Thus it's a form of encapsulation that isolates any changes for object creation to the segment of the code that is behind the "factory", not the code calling the "factory". For instance, using a factory, it's relatively trivial to add new types that the factory-method can create, but none of the previous code that is making a call to the factory has to change. You merely need to create a new derived class for the new object you want to create, and for any new code that desires that new object, you pass the correct new arguments. All the old arguments still work, and there are not changes that need to take place in the code with regards to returned pointer-types, etc.
The reason for using smart-pointers with the factory is to avoid memory leaks that can occur when pointer-ownership is ambiguous. For instance the factory has to return a pointer since it is dyanmically creating the object. The question then becomes who cleans up the pointer in order to avoid either dangling pointers or memory leaks? Smart pointers clear up this ownership problem, and guarantee that memory is not either inadvertently cleaned up when other objects are still pointing to that memory, or that the memory is not simply lost because the last pointer to that memory location goes out of scope without having delete called on it.
I'd advise against putting factory methods in the base class because, technically, Shape knows nothing about Rectangle or Circle. If you add a new shape, such as Donut, then what will you do? Add a new factory method to Shape? You'll clutter the interface in no time. So, IMO, the second method would be better.
If you want to reduce the verbosity of having to create shape_ptr a every time, you could always move the factory methods to the appropriate subclass:
class Circle : public Shape
{
// ...
public:
static shape_ptr make(float radius)
{
return shape_ptr(new Circle(radius));
}
};
// ...
vect.push_back(Circle::make(5.0f));
Since there is std::unique_ptr, I assume the compiler supports C++11. In that case, let me offer the third option:
vect.emplace_back(new Circle(10));
vect.emplace_back(new Rectangle(5,4));
(About .emplace_back: push_back vs emplace_back)
With this you don't need to repeat the shape_ptr, and you don't need to declare a new factory method to Shape whenever you add a new subclass.
Edit: In C++14, you can use std::make_unique to get rid of the raw new call.
vect.emplace_back(std::make_unique<Circle>(10));
vect.emplace_back(std::make_unique<Rectangle>(5, 4));
Related
So I want to override the pure abstract method in my derived classes but I got this error. Can someone help me see what happened and how can I complete it.
My Device class;
class Device {
public:
Device();
Device(const Device& orig);
virtual ~Device();
virtual Device Clone() = 0;
}
And my derived class;
class Radar : public Device {
public:
Radar();
// Radar(const Radar& orig); // commenting so the compiler using its default copy constructor
virtual ~Radar();
Radar Clone();
};
Source file for my Radar class;
Radar Radar::Clone() {
return *(new Radar(*this));
}
If I use Device type in my Clone method in Device class, it will pop-up that Device is an abstract class.
If I use void type (which I'm assuming it's not what I want to have), it will show that I haven't implement this method.
What should I do?
Your Clone method will need to return pointers to the cloned objects... covariant return types only work that way (as returning by value is asking the caller to copy the returned value to the stack - that would be a memory leak when you've allocated it with new).
So, it should be:
virtual Device* Clone() = 0;
...and later...
Radar* Clone(); // YES, it should be Radar* here - that uses C++'s support for
// "covariant return types", see also "UPDATE" discussion
Radar* Radar::Clone()
{
return new Radar(*this);
}
UPDATE - further explanation as requested
So, the idea with a clone function is that it can return a deep copy of whatever actual derived type your Device* is currently addressing. Given that derived type might add data members that Device lacked, it could be a larger object, and the caller has no ability to reserve the right amount of stack space in which to store it. For that reason, the object needs to be allocated dynamically with new, and the predictably-sized Device* is the caller's way to access the new object. It's legal for the clone function to return a Radar* though - all that means is that client code that knows at compile time that it is dealing with a Radar and clones it can continue to use it as a Radar - accessing any extra members that Radar provides.
Hope that helps clarify things. You might also want to do some background reading on Object Oriented programming.
A classic approach to implementing this cloning technique is to use covariant return types for the Clone() method. Coupled with modern RAII techniques (e.g. unique_ptr et. al.) it offers a very flexible and safe combination to manage and clone the objects appropriately.
One of the advantages of the covariant return type is that you are able to obtain a clone an object (a deep copy) and the return type is at the same level in the hierarchy as the argument (i.e. the return is not always to the base class) and no immediate casting is required. In C++, pointers and references support covariance, values do not support covariance.
Using a smart pointer such as unique_ptr is advised over raw painters to avoid memory leaks. The clone_unique factory is modelled on the corresponding make_unique utility from the standard library and returns a unique_ptr. It contains explicit type checks on the class hierarchy of the argument and target types.
The solution does require use of std::unique_ptr. If not available with your compiler, boost provides alternatives for these. There are a few other newer C++ language features, but these can be removed if required.
#include <type_traits>
#include <utility>
#include <memory>
class Device {
public:
virtual Device* Clone() const = 0;
};
class Radar : public Device {
public:
virtual Radar* Clone() const override {
// ^^^^^^ covariant return compared to Device::Clone
return new Radar(*this);
}
};
// Clone factory
template <typename Class, typename T>
std::unique_ptr<Class> clone_unique(T&& source)
{
static_assert(std::is_base_of<Class, typename std::decay<decltype(*source)>::type>::value,
"can only clone for pointers to the target type (or base thereof)");
return std::unique_ptr<Class>(source->Clone());
}
int main()
{
std::unique_ptr<Radar> radar(new Radar());
std::unique_ptr<Device> cloned = clone_unique<Device>(radar);
}
Sample code.
See this related answer for a longer example.
Please try the following signature
virtual Device& Clone() = 0;
or
virtual Device* Clone() = 0;
//Body
Device& Radar::Clone() {
return Radar(*this));
}
I am creating an application that allows a user to define dimensions for different shapes and returns the area to the user using the dimensions they specified.
My base class is Shape. Derived classes are Triangle, Circle, Square and Rectangle.
I have created an array of Shape in the hope of creating and storing instances of any of the derived classes in the array during runtime.
Shape** shape = new Shape*[TOTAL_SHAPES];
shape[i] = new Circle(radius);
I have managed this, however I am unable to access the instantiated classes methods. Sorry if this is a stupid question I am fairly new to C++.
Let's assume your types had the following definition
class Shape {
public:
void Method1() { ... }
};
class Circle : public Shape {
void Method2() { ... }
}
With this definition you could access methods on Shape by doing the following
shape[i]->Method1();
In this context though it wouldn't be possible to access Method2 though because the compiler only knows about Shape, not Circle.
shape[i]->Method2(); // Error!
You have three options:
Make Shape an abstract base class and call virtual methods that are members of Shape
Use static_cast to cast from a Shape* to a Circle*, and call methods through that.
Use dynamic_cast to cast from a Shape* to a Circle*, and call methods through that.
The first option is likely best in many cases. Among other reasons, you almost surely need to have a virtual destructor (which can be a by-product of making Shape an ABC), and you may prefer to not have to know what type of object is being pointed to, rather you'd like to simply call methods on whatever it may be. If you can use this idiom, use it.
The second option is dangerous. You must absolutely know that the object being pointed to is a Circle (or whatever) in order to use static_cast, else you will get Undefined Behavior.
The third option is only possible if your class is polymorphic, which means Shape must have at least one virtual method. You surely should have a virtual destructor, and this would serve that purpose.
How about that:
shape[i]->aMethod();
For starters, I highly recommend using a smart pointer wrapper instead of using raw pointers (especially if you are new to the language).
std::vector<std::shared_ptr<Shape>> shapes(TOTAL_SHAPES);
That will define a vector with an initial size of TOTAL_SHAPES.
To the root of your problem, any method you wish to call using a Shape* must be valid for Shape, or you must do a risky downcast to the appropriate type. For example:
class Shape
{
public:
// constructors and other methods go here
virtual ~Shape() { } // virtual destructor
virtual void Draw() { } // virtual function to be used by derived classes
};
class Circle
{
public:
// ...
virtual ~Circle() { }
virtual void Draw() { } // override the virtual function
};
Then, in your application code,
std::vector<std::shared_ptr<Shape>> shapes(TOTAL_SHAPES);
shapes[0] = std::make_shared(new Circle);
shapes[0]->Draw(); // calls Circle::Draw
Note that depending on your usage, std::unique_ptr may replace std::shared_ptr.
This following question is a bit hard for me to formulate, but please bear with me, and let me know if I can help in clearing anything up.
I am writing a general-purpose simulation for 3D shapes. I am using a base class:
class Shape{
public:
...
virtual double return_volume() =0;
private:
vector<double> coordinates;
...
};
Now, since I don't know what shape the user will choose, I derive several classes from this. (e.g.: Sphere, Cube, Tetrahedron, etc.)
So far, everything is fine.
The main problem comes in the form that I have a Controller class, which launches and operates the simulation. As a private member, it should have a vector of multiple shapes (all of the same type. e.g.: 15 spheres, or 10 cubes, etc.)
class SimulationControl{
public:
void runsimulation();
private:
vector<Shape> all_shapes;
...
};
I wanted to simply initialize this private member with a non-default constructor.
Now, before I knew what I had done, Eclipse already told me that "The type 'Shape' must implement the inherited pure virtual method 'Shape::return_volume'"
I understand the error message and my mistake, of course, but I still don't understand how I can solve it.
What I would love to be able to do is to leave the type of vector undefined, and then simply create it via the constructor with the correct derived class at runtime, when I know which type of simulation the user chose.
Is is somehow possible to do that? Thanks
I'm not going to jump on the bandwagon and suggest using pointers in your container, whether smart or dumb. This is the perfect opportunity to use the PIMPL idiom.
The idea is that the class is simply a wrapper for the actual implementation, and calls a pointer to another object when a call is made to it. The pointer contained within the wrapper can be polymorphic so that it can implement the functions however it sees fit.
class Shape{
public:
Shape() { pImpl = NULL; }
Shape(const Shape& from) { pImpl = from.pImpl->clone(); }
~Shape() { delete pImpl; }
Shape& operator=(const Shape& from) { pImpl = from.pImpl->clone(); }
...
double return_volume() { return pImpl->return_volume(); }
private:
ShapeImpl * pImpl;
...
};
class ShapeImpl{
public:
...
virtual ShapeImpl* clone() const =0;
virtual double return_volume() =0;
private:
vector<double> coordinates;
...
};
Because the Shape class contains a pointer you'll need to implement the rule of three and create a destructor, copy constructor, and operator=. The defaults for the copies will certainly do the wrong thing - they'll only copy the pointer value without creating a new copy of the pimpl object to go with them. Since a vector copies elements around these functions are certain to get called.
Use (smart) pointers.
You cannot instantiate an abstract class, and even if you could, that would probably not be what you want, since you wouldn't be able to create aliases of those shapes.
You should change the definition of your SimulationControl class into something more similar to this (assuming shared ownership for your shapes here - if SimulationControl is the only owner of your shapes, rather use unique_ptr instead of shared_ptr):
#include <memory>
class SimulationControl {
public:
void runsimulation();
private:
std::vector<std::shared_ptr<Shape>> all_shapes;
...
};
Then, you could create instances of your shapes and add them to the all_shapes collection as follows (supposing MyShape is a concrete, default-constructible class derived from Shape):
std::shared_ptr<MyShape> pShape = std::make_shared<MyShape>();
pShape->set_vertices(...); // I guess the class will have a member function
// that allows setting the shape's vertices...
all_shapes.push_back(pShape);
You can only do polymorphism by pointer or reference. Try using vector<Shape*>.
Now that you are using pointers you'll have to manage the memory for them, but that is another set of questions. Try to use smart pointers if you can, or be very careful if you can't. If you are using C++11, std::vector<std::unique_ptr<Shape>> might fit the bill for you.
class base{
.....
virtual void function1();
virtual void function2();
};
class derived::public base{
int function1();
int function2();
};
int main()
{
derived d;
base *b = &d;
int k = b->function1() // Why use this instead of the following line?
int k = d.function1(); // With this, the need for virtual functions is gone, right?
}
I am not a CompSci engineer and I would like to know this. Why use virtual functions if we can avoid base class pointers?
The power of polymorphism isn't really apparent in your simple example, but if you extend it a bit it might become clearer.
class vehicle{
.....
virtual int getEmission();
}
class car : public vehicle{
int getEmission();
}
class bus : public vehicle{
int getEmission();
}
int main()
{
car a;
car b;
car c;
bus d;
bus e;
vehicle *traffic[]={&a,&b,&c,&d,&e};
int totalEmission=0;
for(int i=0;i<5;i++)
{
totalEmission+=traffic[i]->getEmission();
}
}
This lets you iterate through a list of pointers and have different methods get called depending on the underlying type. Basically it lets you write code where you don't need to know what the child type is at compile time, but the code will perform the right function anyway.
You're correct, if you have an object you don't need to refer to it via a pointer. You also don't need a virtual destructor when the object will be destroyed as the type it was created.
The utility comes when you get a pointer to an object from another piece of code, and you don't really know what the most derived type is. You can have two or more derived types built on the same base, and have a function that returns a pointer to the base type. Virtual functions will allow you to use the pointer without worrying about which derived type you're using, until it's time to destroy the object. The virtual destructor will destroy the object without you knowing which derived class it corresponds to.
Here's the simplest example of using virtual functions:
base *b = new derived;
b->function1();
delete b;
its to implement polymorphism. Unless you have base class pointer
pointing to derived object you cannot have polymorphism here.
One of the key features of derived classes is that a pointer to a
derived class is type-compatible with a pointer to its base class.
Polymorphism is the art of taking advantage of this simple but
powerful and versatile feature, that brings Object Oriented
Methodologies to its full potential.
In C++, a special type/subtype relationship exists in which a base
class pointer or a reference can address any of its derived class
subtypes without programmer intervention. This ability to manipulate
more than one type with a pointer or a reference to a base class is
spoken of as polymorphism.
Subtype polymorphism allows us to write the kernel of our application
independent of the individual types we wish to manipulate. Rather, we
program the public interface of the base class of our abstraction
through base class pointers and references. At run-time, the actual
type being referenced is resolved and the appropriate instance of the
public interface is invoked. The run-time resolution of the
appropriate function to invoke is termed dynamic binding (by default,
functions are resolved statically at compile-time). In C++, dynamic
binding is supported through a mechanism referred to as class virtual
functions. Subtype polymorphism through inheritance and dynamic
binding provide the foundation for objectoriented programming
The primary benefit of an inheritance hierarchy is that we can program
to the public interface of the abstract base class rather than to the
individual types that form its inheritance hierarchy, in this way
shielding our code from changes in that hierarchy. We define eval(),
for example, as a public virtual function of the abstract Query base
class. By writing code such as
_rop->eval();
user code is shielded from the variety and volatility of our query language. This not only allows for the addition, revision,
or removal of types without requiring changes to user programs, but
frees the provider of a new query type from having to recode behavior
or actions common to all types in the hierarchy itself. This is
supported by two special characteristics of inheritance: polymorphism
and dynamic binding. When we speak of polymorphism within C++, we
primarily mean the ability of a pointer or a reference of a base class
to address any of its derived classes. For example, if we define a
nonmember function eval() as follows, // pquery can address any of the
classes derived from Query
void eval( const Query *pquery ) { pquery->eval(); }
we can invoke it legally, passing in the address of an object of any of the
four query types:
int main()
{
AndQuery aq;
NotQuery notq;
OrQuery *oq = new OrQuery;
NameQuery nq( "Botticelli" ); // ok: each is derived from Query
// compiler converts to base class automatically
eval( &aq );
eval( ¬q );
eval( oq );
eval( &nq );
}
whereas an attempt to invoke eval() with the address of an object not derived from Query
results in a compile-time error:
int main()
{ string name("Scooby-Doo" ); // error: string is not derived from Query
eval( &name);
}
Within eval(), the execution of pquery->eval(); must invoke the
appropriate eval() virtual member function based on the actual class
object pquery addresses. In the previous example, pquery in turn
addresses an AndQuery object, a NotQuery object, an OrQuery object,
and a NameQuery object. At each invocation point during the execution
of our program, the actual class type addressed by pquery is
determined, and the appropriate eval() instance is called. Dynamic
binding is the mechanism through which this is accomplished.
In the object-oriented paradigm, the programmer manipulates an unknown instance of a bound but infinite set of types. (The set of
types is bound by its inheritance hierarchy. In theory, however, there
is no limit to the depth and breadth of that hierarchy.) In C++ this
is achieved through the manipulation of objects through base class
pointers and references only. In the object-based paradigm, the
programmer
manipulates an instance of a fixed, singular type that is completely defined at the point of compilation. Although the
polymorphic manipulation of an object requires that the object be
accessed either through a pointer or a reference, the manipulation of
a pointer or a reference in C++ does not in itself necessarily result
in polymorphism. For example, consider
// no polymorphism
int *pi;
// no language-supported polymorphism
void *pvi;
// ok: pquery may address any Query derivation
Query *pquery;
In C++, polymorphism
exists only within individual class hierarchies. Pointers of type
void* can be described as polymorphic, but they are without explicit
language support — that is, they must be managed by the programmer
through explicit casts and some form of discriminant that keeps track
of the actual type being addressed.
You seem to have asked two questions (in the title and in the end):
Why use base class pointers for derived classes?
This is the very use of polymorphism. It allows you to treat objects uniformly while allowing you to have specific implementation. If this bothers you, then I assume you should ask: Why polymorphism?
Why use virtual destructors if we can avoid base class pointers?
The problem here is you cannot always avoid base class pointers to exploit the strength of polymorphism.
If I want to clone a polymorphic object in C++ (i.e. an instance of a class A which is derived from some other class B), the easiest way seems to give B a virtual clone member function, that has to be overridden by A and looks like this
A* clone(){
return new A(*this);
}
My problem is, that I find this unnecessary boilerplate code, as this is almost always needed, if one wants to use run-time polymorphic features of C++. How can it be circumvented?
Thanks
Why I need this:
My use case can be abstracted to the following example:
I have a class Integral, which evaluates the integral of some function. Do do this, they have a member which is a pointer to the class MathFunction. This abstract class contains a pure virtual function evaluate which takes one argument. I I wanted to implement the power function I would create a class PowFunction : class MathFunction. This class would have a member exponent and the function evaluate would look like this:
double evaluate(x){
return pow(x,exponent);
}
As stated the member MathFunction of class Integral has to be polymorhpic, which requires it to be a pointer. To answer the questions of the commenters with another question. Why wouldn't I want to be able to make copies of MathFunction objects?
I really want the Integral to "own" its MathFunction, meaning, that it can alter the parameters (like exponent) without changing the MathFunction of any other Integral object. This means every Integral needs to have its own copy. This requires a clone() function for MathFunctions, doesn't it?
One alternative i thought of: If several Integral objects can share the same MathFunction via a pointer to the same address, I could create copies of Integral objects without the need to copy the MathFunction. But in this case I would have to make all the properties const or somehow readonly, which is not very elegant either. Also, which Integral object should handle delete the MathFunction object?
Why you need this:
Are you seriously saying, that as soon as you work with polymorphic objects you don't ever need a copy operation? What makes polymorphic object different from other objects in this respect?
Using this argumentation, you could also throw the copy constructor and copy assignment operator out of the C++ standard!
Reduce the need to clone polymorphic objects. Really, I rarely find the need for this in my own code, and the comments on the question suggest that I'm hardly alone in the opinion that if you find yourself cloning everything, you're probably designing it wrong.
Of course, never to be unhelpful, you could indeed use the Curiously Recurring Template Pattern.
template<typename T> struct Clone {
virtual T* clone() { return new T(static_cast<const T&>(*this)); }
};
I handled this issue with a macro... it's ugly, but it works to avoid inconsistencies.
/** An interface that can be inherited by any class that wants to provide a Clone()
* method that will return a copy of itself.
*/
class ICloneable
{
public:
ICloneable() {}
virtual ~ICloneable() {}
virtual ICloneable * Clone() const = 0;
};
#define DECLARE_STANDARD_CLONE_METHOD(class_name) virtual ICloneable * Clone() const {new class_name(*this);}
[...]
public MyCloneableClass : public ICloneable
{
public:
MyCloneableClass() {}
DECLARE_STANDARD_CLONE_METHOD(MyCloneableClass);
};