2

Hello I am having a small issue with storing derived type objects within a 2-dimensional array of the base type without loosing the derived type stored in the array.

For example there is the following Base and Derived class:

class Base{

}

class Derived: public Base{

}

There is a point where I have a Base object created like the following:

Base objectB;

Then I cast the above object to the type of the Derived class like the following:

Base *referencePointer = &objectB;
Derived *derivedPointer = static_cast<Derived*>(referencePointer);

At this point everything is working correctly (if I print out the type of derivedPointer it is of type Derived).

Now I have a 2 dimensional array of type Base class initialized as the following:

Base *baseArray[5][5];

Now I input the derivedPointer value into the array as the following:

baseArray[x][y] = derivedPointer;

This is where the problem occurs as it stores in the referencePointer but it becomes of Base type (object slicing) and I am unsure as to how I would go about storing the referencePointer value and keep its type within an array of type Base.

Any help is much appreciated,

Thank you!

Baraa
  • 687
  • 1
  • 9
  • 26
  • There are more than one derived class that I want to input in one array for the reason that the different objects will have different functionality. Imagine that there is a video game with different types of players that are able to move different based on there type but they all have certain base functionality that are the same. – Baraa Mar 10 '14 at 23:04
  • 3
    `objectB` is of base type but you cast it to a derived type (a type that is related but not a type `objectB` actually **is**). This is undefined behavior and will not work as you expect. There also is no object slicing going on because you're working with pointers not object values. – Captain Obvlious Mar 10 '14 at 23:04
  • @CaptainObvlious I am a bit new to the object slicing concept I thought that is what was going on here, but I might be wrong. The cast seems to work though? I print out using typeid(derivedPointer).name() and it prints out the type being of type Derived which means the cast works but when I print out the following typeid(baseArray[x][y]).name() after inputting the derivedPointer it prints out the type being of type Base. – Baraa Mar 10 '14 at 23:08
  • Undefined behavior means that anything can happen including the code working **exactly** as expected. Build it on another platform and run it and the results may be quite shocking. Add some member variables or virtual functions and your code will likely fail in a very spectacular fashion. – Captain Obvlious Mar 10 '14 at 23:17
  • @Baraa, you've got undefined behavior. That means anything can happen, so "seeming to work" is a possible result, but it certainly isn't correct code. Your example classes are not polymorphic, so the compiler has no way to determine the real type of the object that a pointer is pointed to. In any event, I don't see in any of your code where you actually create a `Derived`, so there are no actual `Derived` objects in existence. If the compiler is reporting that an object is pointing to a `Derived`, it would be because the undefined behavior is confusing it. – Adam H. Peterson Mar 10 '14 at 23:17
  • 1
    @Baraa, actually, your `typeid()` snippets are identifying the type of the pointer, not the type of the pointed-at object. – Adam H. Peterson Mar 10 '14 at 23:22
  • @CaptainObvlious & Adam H. Peterson Thanks for the information, I am starting to understand this a bit more...I am going to research this a bit more and get back to you. – Baraa Mar 10 '14 at 23:29
  • I agrre with @CaptainObvlious. I see no slicing issues here. The objects pointed to in your table have not been sliced. Imagine the base class has n>0 pure virtual methods. Note that none of the objects in the table could be instanced unless they were derived and the derived provided the missing methods. THUS, is should be clear that the table is not pointers to 'sliced' base class objects, but rather pointers to full and complete derived objects, and these are objects for which any method not defined by the base is provided by the derived object instance. – 2785528 Mar 11 '14 at 00:40

2 Answers2

1

video game with different types of players that are able to move different based on there type but they all have certain base functionality that are the same.

Imagine that the 'certain base functionality' is implemented in the base class. These methods can easily be made available to any derived classes as public or protected methods. Thus eliminating duplicate code.

Now imagine the base class provides a virtual method "void move(CoordinatesXYZ_t to, VelocityXYZ_t vel, AccelerationXYZ_t acc)".

Simply by adding a (virtual) method with the same signature in a derived class, each derived object can provide their own unique response to the gaming engine's move command. There is no need for the gaming engine to know what type of derived object it is, the correct virtual method will be invoked.

Downcast'ing is simply not needed. The game engine can be written so that it simply does not need to care what kind of derived class it is dealing with - as long as the derived object conforms to the interface. The game engine invokes a virtual method, which will result in the invocation of the appropriate derived object method.

The actual method can be unique for every member of the 2 dimensional array of base pointers.

The actual method can even do nothing (i.e. a tree probably does not move.)

And the derived class does not have to provide a move method unless the desired behaviour is different from what the base class' move method provides.

2785528
  • 5,438
  • 2
  • 18
  • 20
0
Derived *derivedPointer = static_cast<Derived*>(referencePointer);

This is a mistake because referencePointer actually points to a Base object. The compiler won't magically tack on extra bits to the Base object to turn it into a Derived object. To avoid this error, use dynamic_cast instead of static_cast. Then you will be able to detect failure.

Note, Base needs to be polymorphic for this to work, it must have at least 1 virtual function.

By the way, this is nothing to do with slicing. Even if referencePointer pointed to a Derived, that's fine: you have a 2-D array of pointers, it's fine to put in a Base *, which might point to an object of Derived type. Slicing would be if you had a 2-D array of Base.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • _"The compiler won't magically tack on extra bits to the Base object to turn it into a Derived object. To avoid this error..."_ could easily be taken to mean that using `dynamic_cast` _will_ tack on the required "extra bits". It would also be better served with an example using `dynamic_cast `showing the check for a null pointer value. Bonus: cover the resulting `bad_cast` exception when converting to a reference type. – Captain Obvlious Mar 11 '14 at 01:44
  • Feel free to edit my answer with your suggestions :) – M.M Mar 11 '14 at 02:25
  • Does my avatar look black to you? – Captain Obvlious Mar 11 '14 at 22:38