Polymorphism & Pointers to arrays
You can't treat arrays polymorphically, so while new B[100]
creates an array of B
objects and returns a pointer to the array - or equivalently the first element of the array - and while it is valid to assign this pointer to a pointer to a base class, it is not valid to treat this as a pointer into an array of A
objects.
The principal reason that you can't is that (typically) derived objects are a different size to their base classes, so attempting to access the array as an array of base class objects will not use the correct offset to get a pointer to the next base class subobject of the next member of the derived class array.
Why does polymorphism not apply on arrays in C++?
You get undefined behavior because operator delete[]
has no idea what kind of object is stored in the array, so it trusts the static type to decide on offsets of individual objects. The standard says the following:
In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.
The array's static type needs to match the element type that you use for the allocation:
Derived* p = new Derived[4]; // Obviously, this works
This Q&A goes into more details on the reason why the standard has this requirement.
As far as fixing this behavior, you need to create an array of pointers, regular or smart (preferably smart to simplify memory management).
Array of polymorphic objects
In very simple terms:
unique_ptr
is the owner of the object. It manages the lifetime of the owned objectreference_wrapper
wraps a pointer to an object in memory. It does NOT manage the lifetime of the wrapped object
You should create an array of unique_ptr
(or shared_ptr
) to guarantee the release of the object when it's not needed anymore.
C++ polymorphism of a object in an array
As others have pointed out, the convenient and common way doesn't work like that. Fixing it results in code which is at odds with the restrictions of your target platform. You can, however, emulate polymorphism differently in several different ways.
You can segregate the objects by type like this:
const Triangle tris[] = {tri1, tri2, ...};
const Rectangle rects[] = {rect1, rect2, ...};
// for correct order, if needed
const Shape * const shapes[] = {&tris[0], &rects[2], &rects[0], ...}:
You still need to make all methods (that behave differently for the various types) virtual
, and you pay an extra pointer (two if you count the vtable pointer, which would be a bit unfair) per object.
You could also remove everything virtual
in favor of an explicit tag:
enum ShapeKind { Triangle, Rectangle, Pentagon };
struct Shape {
ShapeKind kind;
int sides;
...
};
Use a union
if the various subclasses need very different member data.
This has numerous severe restrictions and leads to rather ugly code, but can work well. For example, you need know your hierarchy up front and the subclasses need to be roughly the same size. Note that this is not necessarily faster than the virtual
alternative, but when it's applicable it can take less space (a byte instead of a vtable pointer) and make introspection leaner.
Polymorphism and array of pointers (C++)
Add
should take a pointer:
void Add(CControl * newElement){
elements[elemCnt++] = newElement;
}
then you can call it like this
c.Add( new Button(...) );
c.Add( new Input(...) );
If you really cannot change the calling code, you need to somehow create a copy of the temporary.
E.g. by implementing a virtual Clone
method in CControl
, Input
, Button
an call it in Add
.
void Add(const CControl & newElement){
elements[elemCnt++] = newElement.Clone();
}
polymorphism c++, trying to access member functions of classes that are derived from abstract base class
No, what you are trying to do is not polymorphism. It is actually the exact opposite of polymorphism.
Polymorphism is using only your base class interface to manipulate any of your derived classes, including those that are not written yet.
For example, if you want your items to have titles, you define a virtual (possibly pure) method getTitle()
in your base class, and implement it in your derived classes. This way you can get a title of any item in your collection without knowing or caring about its exact type.
Related Topics
Can a Variable Be Declared Both Static and Extern
What's the Real Reason to Not Use the Eof Bit as Our Stream Extraction Condition
Lambdas and Capture by Reference Local Variables:Accessing After the Scope
C++11 Std::Mutex in Visual Studio 2012 Deadlock When Locked from Dllmain()
Qmake: How to Remove Compiler Flag for a Certain Project, Without Changing Qmake.Conf
Where Should Non-Member Operator Overloads Be Placed
How Disastrous Is Integer Overflow in C++
How to Call a Pointer-To-Member-Function
How to Draw a Point (On Mouseclick) on a Qgraphicsscene
Qt Moc with Implementations Inside of Header Files
Removing '#Include <Algorithm>' Doesn't Break the Code
Print 2-D Array in Clockwise Expanding Spiral from Center