c++ casting base class to derived class mess - c++

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.

Related

Constexpr check if static_cast of pointers between two hierarchically related types changes the pointer value

For some specialised allocator-like thing I'm implementing, I would like to require that all objects that are going to be stored share a common base class as their first subobject. This allows me to keep a single pointer the common base class as both an indicator of the start of the object as well as to regain access to the original object using static_cast, assuming I have some way to know the type of the original object.
Specifically, I would like the following equality to always hold for any pointer ptr
to a type Base, assuming no virtual inheritance between Derived and Base.
reinterpret_cast<char *>(static_cast<Derived*>(ptr)) == reinterpret_cast<char *>(ptr)
I assume that this equation holds either for all valid pointers of a given class hierarchy,
or it doesn't hold for any valid pointer of a given class hierarchy. Is that correct?
Therefore, that check should be possible to be made at compile-time, without even knowing the runtime value of ptr. So is there a constexpr method to check if a static_cast between two related types changes the pointer value? The above equality seems not acceptable, as I found no constexpr way to create test pointer.
You are asking about is pointer interconvertibility. There is a related trait std::is_pointer_interconvertible_base_of which isn't implemented yet in gcc and clang. See also the paper and issue. Pointer interconvertible types have the same address and their pointers can be casted between with reinterpret_cast.
I assume that this equation holds either for all valid pointers of a given class hierarchy, or it doesn't hold for any valid pointer of a given class hierarchy. Is that correct?
As you already noted, virtual inheritance foils this, but so does failure of the standard layout criteria. If Derived has multiple base classes, and Base isn't the first, it fails.
The question fails to motivate the requirement for having the same address. If that is not a requirement, static_cast to upcast from Derived to Base and to downcast from Base to Derived will just work so long as the inheritance relationship is not virtual, unambiguous, and public.

Explicitly passing an vector of shared_ptr into a function

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.

C++ how to create a array of subclass use baseclass

suppose I have three class like these:
class base {
//some data
method();
};
class sub1 : base {
//some data
//overrides base method
method();
};
class sub2: base {
//some data
//overrides base methods
method();
};
How can I create a array mixed with sub1 and sub2? then calling subclass method with base?
Ok, let's sort this out. First of all, you probably meant virtual method();, probably with a return type, maybe with parameters. Without virtual, base class pointers and references won't know about the overridden method. Second, make the destructor virtual. Do this until you know why you need to (delete (base*) new derived;) - then keep doing this until all your neighbourhood knows why you need to. Third, the sad thing is, all std. C++ containers are homogeneous (non-std. heterogeneous container-like objects in Boost exist), thus you need to find an object that's common and that's somehow able to handle these types. Common choices are:
Common base class pointer, in your case, base*. This conventionally owns the objects and is manually (de)allocated (that is, you need to call new and delete). This is the most common choice. You might try smart pointers later, but let's get the basics first.
Common base class reference, in your case, base&. Common convention is that this doesn't own the object (albeit this is not a language restriction), thus it's mainly used for referring to objects that are stored in another container. Since you need to store them somewhere, I wouldn't opt for this now, but it might come handy later.
std::variant<> (or boost::variant<>), this is a discriminated union, that is, a class that stores one and only one of the listed items and knows which one it stores. You don't need a common base class, but even if you have one, it's cool because it tends to store objects locally, thus might be faster when you have enough cache.
union, which is like variant, but does not know the type being stored. Local storage is guaranteed, as well as UB if you write one field and read another
Compiler-specific solutions. If you know that your classes are of the same size (in this case, they are) and you know for sure that you have untyped memory, then you might store the base class and it'll 'just work', provided you always take the address and -> operator. Note that this is UB squared, I just list this because you'll likely encounter similar code. Also note that simply having a union does not remove UB in this case - until we have access to virtual table pointer, this can only be done by manually handling virtual functions.

Object slicing within a two-dimensional array in c++

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.

C++ converting back and forth from derived and base classes

I was wondering if there is a way in C++ to accomplish the following:
I have a base class called ResultBase and two class that are Derived from it, Variable and Expression. I have a few methods that do work on vector<ResultBase> . I want to be able to pass in vectors of Variable and Expression into these methods. I can achieve this by creating a vector<ResultBase> and using static_cast to fill it with the members from my vector of Variable/Expression. However, once the vector has run through the methods, I want to be able to get it back as the vector of Result/Expression. I'll know for sure which one I want back. static_cast won't work here as there isn't a method to reconstruct a Variable/Expression from a ResultBase, and more importantly I wouldn't have the original properties of the Variables/Expressions
The methods modify some of the properties of the ResultBase and I need those changes to be reflected in the original vectors. (i.e. ResultBase has a property called IsLive, and one of the methods will modify this property. I want this IsLive value to be reflected in the derived class used to create the ResultBase
Whats the easiest way to accomplish this?
vector<ResultBase *> should fix your slicing problem - a vector<ResultBase> will never contain classes derived from ResultBase, but rather copies that "slice off" e.g. Expression by copying the ResultBase part of it.
See What is object slicing? for a detailed explanation of slicing.
One possibility is to change your functions that do work on vector<ResultBase> into function templates that do work on vector<T>, with T a template parameter. To be even more generic, perhaps the functions can operate on a pair of iterators instead of a particular container type.
You can then call them with a vector<Variable> or vector<Expression> instead of a vector<ResultBase>, as long as Variable and Expression are both proper substitutes for ResultBase, as a derived class should be.
Alternatively as Erik says you can use pointers to get polymorphic behavior with containers. For ease of memory management, a vector of smart pointers or a Boost ptr_vector is usually preferred to a vector of raw pointers.
There's no way to convert an instance of a derived class to base and then back to derived, while preserving its original value, for pretty much the same reason that it's not possible to convert from int to char and then back, preserving the original value. If all else fails, you could perhaps bodge something together where you use the modified ResultBase objects to somehow update the original Variable or Expression objects with any changes made by the functions.