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!
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.
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.
Related
I have a Base and a number of Derived classes that all define a common method foo. foo is defined with a definition in Base class and is virtual. Derived objects can call Base::foo() in their own foo methods if they wish. Each Derived class has its own set of constructor parameters different from that of the Base class.
I know the terminology is funky but when I say each Derived class I mean there are class definitions like class Parrot: public Base and class Dog: public Base.
I have the following method
void addImportantObjects(std::vector<std::shared_ptr<Base>> objects);
That will eventually save each of those shared pointers to various internal vectors so it can iterate through them and call foo and have the proper foo of the Derived class called.
I am going to be calling this method frequently and I want to get it as small/functional looking and easy to read as possible. Obviously it would be nice to hide away the construction of the vector or the pointer casts if possible.
This is the best I have been able to do thus far
std::vector<std::shared_ptr<Base>> objs;
objs.push_back(std::dynamic_pointer_cast<Base>(std::make_shared<Derived>(args)));
objs.push_back(std::dynamic_pointer_cast<Base>(std::make_shared<Derived2>(args)));
addImportantObjects(objs);
You can see a lot of space is wasted with the casting and the push_backs and the shared pointer syntax. If I had a long list of objects I wished to add it would be be a lot of code.
My question is there any way I could make it look more closer to perhaps
addImportantObjects({Derived(args), Derived2(args)})
In case it is important here these objects will not be referenced outside of the scope of the object with the addImportantObjects method. The shared pointer is just to ensure that internally it does not copy anything as it processes it. Any method that allows this to happen but does not copy the object more than once would be ok.
Imagine I have a class called Test and inside this class I have a list of pointers which their types are all from class Base. Although any pointer which is stored in list is pointer to an object from classes which are derived from class Base. I want to provide a getter() function for a specific derived type which returns the object of specific class. Note that we don't know the index of required pointer inside class.
class Base
{
/// Base class do have a pure virtual function
};
class Derived1
{
};
class Derived2
{
};
Class Test
{
std::vector<Base*> pointers; /// any STL collection... vector may be more frequent
get_derived1_object(); ///
};
I think of some possible implementations of get_derived1_object() like this (And in my opinion both have some problems):
1- storing a copy pointer of Derived1's object's pointer inside class. In case I want to try using unique_pre it is not a good solution.
2- iterate over pointers in order to find which item is from Derived1 class using runtime type checking. (for example trying to use dynamic_cast or sth similar). In my usecase, using runtime type checking is better not to be used.
P.S: having multiple items of each class is not important here because I'm sure I don't have 2 different pointers from same class inside my list and consider it taken care of.
I was wondering if I could find the best solution for providing a function like get_derived1_object (whether from my own given solutions or sth else).
Instead of a vector, use an associative map of std::type_index to base pointer. Ensure that only matching type index is used, and then you don't need dynamic_cast, because we know that the type will match the mapped pointer. That said, use of std::type_index still relies on RTTI. No linear searching is needed.
While I've been working in c++ for a while, I haven't had need to use polymorphic features until now, and I'm very intrigued by them.
If I have a base class ClassA and another ClassB derives from it, I understand that I can have virtual member function in ClassA that, when implemented in ClassB, will be called in a ClassB instance even if that instance is pointed at using a ClassA pointer. Without this virtual keyword, I presume the base class implementation would prevail when using a base class pointer, yet be operating on an object that was instantiated from the subclass, which seems questionable to me if in fact ClassB has its own implementation of the same function that is effectively ignored in such a case.
Is this a correct understanding of polymorphic behavior?
Now the real question is how do you refer to ClassB using a pointer to is base class. I can really only think of two ways:
Create the pointer at the time of instantiation, using a function that returns a base class pointer while actually allocating memory for the subclass instead, using the subclass's constructor. (Does such a creation function have a common name?)
Casting an object using static_cast and assigning it to a pointer to the base class.
Are these the two main techniques for generating base class pointers to objects of a subclass?
The easiest way is to simply assign it, no cast necessary:
ClassA *ptrA = new ClassB;
You're correct that you need the virtual keyword to enable polymorphic behavior. Here's one way to think about it. C++ operates on the static type of an object. When you call ptrA->foo(), the type of the pointer is ClassA*. If that function is not declared virtual, then it will blindly call ClassA's version of the function. There's no other choice. But if foo() is virtual, then it knows to stop and ask, "Wait, what type am I really?" And the answer in that case is ClassB, so it will call ClassB's version.
Also note that you don't need pointers to achieve this. Another common way you'll see polymorphism in action is via a function call:
void bar(ClassA &aObj)
{
aObj.foo();
}
// ...
ClassB bObj;
bar(bObj);
If I were to create a base class called base and derived classes called derived_1, derived_2 etc... I use a collection of instances of the base class, then when I retrieved an element and tried to use it I would find that C++ thinks it's type is that of the base class, probably because I retrieved it from a std::vector of base. Which is a problem when I want to use features that only exist for the specific derived class who's type I knew this object was when I put it into the vector.
So I cast the element into the type it is supposed to be and found this wouldn't work.
(derived_3)obj_to_be_fixed;
And remembered that it's a pointer thing. After some tweaking this now worked.
*((derived_3*)&obj_to_be_fixed);
Is this right or is there for example an abc_cast() function that does it with less mess?
edit:
I had to expand this into another question, the full solutions are shown there. stackoverflow.com ... why-the-polymorphic-types-error-and-cleanup-question
If you store your objects in a std::vector<base> there is simply no way to go back to the derived class. This is because the derived part has been sliced of when storing it in an instance of base class (afterall your vector contains copies of your data, so it happily copies only the base part of your objectes), making the stored object a true instance of base class, instead of a derived class used as a base class.
If you want to store polymorphic objects in the vector make it a std::vector<base*> (or some kind of smartpointer to base, but not base itself) and use dynamic_cast<derived_3*> to cast it to the correct type (or static_cast, if its performance sensitive and you are confident enough that you are trying to cast to the correct type (in that case horrible things will happen if you are wrong, so beware)).
If you are using a vector of base then all your instances are base instances and not derived instances.
If you try to insert a derived instance, the object will be sliced. Inserting into a vector always involves a copy and the target type is determined by the type of the object that the vector holds. A vector cannot hold objects of different types.
Most of the time you shall not need to do this. A carefully designed class hierarchy can handle this by polymorphism (i.e. virtual functions).
If you really need to cast to the derived type, use dynamic_cast operator.
What you are trying to do is not even remotely possible. If the objects stored in your container have type base, then they are base, period. They are not derived objects, they will never become derived objects and they cannot be used as derived objects regardless of what you do.
Your cast through pointers is nothing than just a hack that reinterprets memory occupied by base object as derived object. This is totally meaningless and can only "work" by accident.
I need some answers to basic questions. I'm lost again. :(
q1 - Is this statement valid:
Whenever we define the function to be pure virtual function,
this means that function has no body.
q2 - And what is the concept of Dynamic Binding? I mean if the Compiler optimizes the code using VTABLEs and VPTRs then how is it Run-Time Polymorphism?
q3 - What are VTABLES AND VPTRs and how do their sizes change?
q4 - Please see this code:
class base
{
public:
virtual void display()
{
cout<<"Displaying from base";
}
};
class derived:public base
{
public:
void display(){cout<<"\nDisplaying from derived";}
};
int main()
{
base b,*bptr;
derived d;
bptr=&b;
bptr->display();
bptr=&d;
bptr->display();
}
Output:
Displaying from base
Displaying from derieved
Please can somebody answer why a pointer of base class can point the member function of a derived class and the vice-versa is not possible, why ?
False. It just means any derived classes must implement said function. You can still provide a definition for the function, and it can be called by Base::Function().*
Virtual tables are a way of implementing virtual functions. (The standard doesn't mandate this is the method, though.) When making a polymorphic call, the compiler will look up the function in the function table and call that one, enabling run-time binding. (The table is generated at compile time.)
See above. Their sizes change as there are more virtual functions. However, instances don't store a table but rather a pointer to the table, so class size only has a single size increase.
Sounds like you need a book.
*A classic example of this is here:
struct IBase
{
virtual ~IBase(void) = 0;
};
inline IBase::~IBase(void) {}
This wouldn't be an abstract class without a pure virtual function, but a destructor requires a definition (since it will be called when derived classes destruct.)
1) Not necessarily. There are times when you provide body for pure virtual functions
2) The function to be called is determined at run time.
False. It only means that derived classes must implement the method and that the method definition (if present) at that level will not be consider an override of the virtual method.
The vtable is implemented at compile time, but used at runtime. The compiler will redirect the call through the vtable, and that depends on the runtime type of the object (a pointer to base has static type base*, but might point to an object of type derived at runtime).
vptrs are pointers to an vtable, they do not change size. vtables are tables of pointers to code (might point to methods or to some adapter code) and have one entry for each virtual method declared in the class.
After the edit in the code:
The pointer refers to an object of type base during the first call, but it points to an object of type derived at the second call position. The dynamic dispatch mechanism (vtable) routes the call to the appropriate method.
A common implementation, which may help you understand is that in each class that declares virtual functions the compiler reserves space for a pointer to a virtual table, and it also generates the virtual table itself, where it adds pointers to the definition of each virtual method. The memory layout of the object only has that extra pointer.
When a derived class overrides any of the base class methods, the compiler generates a different vtable with pointers to the final overriders at that level. The memory layout of both the base and the derived class coincide in the base subobject part (usually the beginning), but the value of the vptr of a base object will point to the base vtable, while the value of the vptr in the derived object will point to the derived vtable.
When the compiler sees a call like bptr->display(), it checks the definition of the base class, and sees that it is the first virtual method, then it redirects the call as: bptr->hidden_vptr[0](). If the pointer is referring to a real base instance, that will be a pointer to base::display, while in the case of a derived instance it will point to derived::display.
Note that there is a lot of hand-waving in this answer. All this is implementation defined (the language does not specify the dispatch mechanism), and in most cases the dispatch mechanism is more complex. For example, when multiple inheritance takes place, the vtable will not point directly to the final overrider, but to an adapter block of code that resets the first implicit this parameter offset, as the base subobject of all but the first base are unaligned with the most derived object in memory --this is well beyond the scope of the question, just remember that this answer is a rough idea and that there is added complexity in real systems.
Is this statement valid
Not exactly: it might have a body. A more accurate definition is "Whenever we define a method to be pure virtual, this means that the method must be defined (overriden) in a concrete subclass."
And what is the concept of Dynamic Binding? I mean if the Compiler optimizes the code using VTABLEs and VPTRs then how is it Run-Time Polymorphism?
If you have an instance of a superclass (e.g. Shape) at run-time, you don't/needn't necessarily know which of its subclasses (e.g. Circle or Square) it is.
What are VTABLES AND VPTRs and how do their sizes change?
There's one vtable per class (for any class which has one or more virtual methods). The vtable contains pointers to the addresses of the class's virtual methods.
There's one vptr per object (for any object which has one or more virtual methods). The vptr points to the vtable for that object's class.
The size of the vtable increases with the number of virtual functions in the class. The size of the vptr is probably constant.
Please can somebody answer why a pointer of base class can point the member function of a derived class and the vice-versa is not possible, why ?
If you want to invoke the base class function then (because it's virtual, and the default behaviour for virtual is to call the most-derived version via the vptr/vtable) then you have to say so explicitly, e.g. like this:
bptr->base::display();