I'm currently writing WinRT code, but I imagine this question applies to all C++. Upon user interaction, the framework calls one of my functions passing in a vector with generic Object^ pointers (very similar to void* for you non-WinRT folks). I already know what type of objects are in the vector and I'd like to cast the vector to that object type.
Example:
MyClass::SomeFunction(Vector<Object^>^ myList) {
// Warning: The following line doesn't work!!
Vector<SpecificType^>^ myTypedList = static_cast<Vector<SpecificType^>^>(myList);
// Here, I go on to interact with the templated vector.
...
}
The compiler doesn't allow me to use static_cast. safe_cast throws an exception. dynamic_cast doesn't throw an exception, but returns a null pointer.
Is there a way I can cast this thing, or do I literally have to create a new vector and copy all the members over (casting each from Object^ to SpecificType^ on insertion)?
You cannot cast Vector<Object^> to any other Vector<> because there is no inheritance involved between them. The only thing that you can do is cast each element into the right class. So, if you want a Vector<SpecificType^> you do indeed need to create it anew. Not that it is too hard:
Vector<SpecificType^> specificList;
for (Object^ p : myList)
specificList.push_back(static_cast<SpecificType^>(p));
Related
I am trying to call a child function from a parent instance using explicit down-casting (thanks for pointing out #Aconcagua). As a beginner in C++, I have something like this:
Road currentRoad = ...;
duration = ((SpeedDataRoad) currentRoad).getSpeedProfileTime(dateinMillis, isRightDirection);
class SpeedDataRoad inherits from Road:
class SpeedDataRoad : public Road{
double getSpeedProfileTime(long dateinMillis, bool isRightDirection) {
...
}
However I am getting the error:
No matching conversion for C-style cast from 'Road' to 'SpeedDataRoad'
Any suggestions on what I am doing wrong would be appreciated.
Just to be clear, what I am trying to achieve in Java would be written like this and working correctly:
duration = ((SpeedDataRoad) currentRoad).getSpeedProfileTime(currentTime, isRightDirection);
You suffer from an effect called 'object slicing':
SpeedDataRoad sdr;
Road currentRoad = sdr;
At the second line, sdr is assigned by value to currentRoad, but the latter is not of appropriate type to hold a complete SpeedDataRoad object. So all surplus pieces of SpeedDataRoad are simply cut away and all that remains is a pure Road object only containing the Road parts of original sdr object.
At the same time, as you only have a pure Road object left, you cannot cast it back to SpeedDataRoad object. From where should the now missing parts come from?
This is exactly the same reason why you cannot place polymorphic types directly into a container (like std::vector) of the base class.
What you need are either pointers (if you want to be able to re-assign) or references (to be preferred otherwise):
SpeedDataRoad sdr;
Road& currentRoad = sdr;
// ^ (!)
// or:
Road* currentRoad = &sdr;
Now you can do the cast. But explicit down-casts have a smell of bad design. You might be better off with a polymorphic approach right from the start:
class Road
{
public:
virtual double getSpeedProfileTime(long, bool) = 0;
// ^ pure virtual
// alternatively, you can provide a default implementation
};
class SpeedDataRoad : public Road
{
public:
double getSpeedProfileTime(long, bool) override
{ /* ... */ }
};
Now you can simply have:
SpeedDataRoad sdr;
Road& currentRoad = sdr;
double profile = currentRoad.getSpeedProfileTime(0, false);
As being virtual, you'll always get the right variant of the function, no matter which sub-class we have at all and in which way it might override the function...
Side note 1: Instead of old C-style casts, you might prefer the more modern C++ casts, you can control more fine grained what you actually want to do:
Road* someRoad = ...;
SpeedDataRoad* sdr = static_cast<SpeedDataRoad*>(someRoad);
SpeedDataRoad* sdr = dynamic_cast<SpeedDataRoad*>(someRoad);
You would use a static_cast, if you are 100% sure that the object only can be of desired type. You avoid any run-time tests that wouldn't serve anything at all in this situation (you are 100% sure anyway, remember?). Curiously recurring template pattern is a typical scenario for.
If you cannot be sure about the type, then dynamic_cast comes into play, it will do some run-time type checking and just return a null pointer (if used on pointers) or throw a std::bad_cast (if used on references), if the actual type is not of desired type (or a sub class of). Such a scenario can arise when different polymorphic types are stored in a vector (as pointers to base class, see above). But again: Needing a cast at all might be a hint to your design being flawed...
(For completeness: There are yet const_cast and reinterpret_cast, but you should stay away from these unless/until you really, really know what you do.)
Side note 2: Differences to Java.
In Java, we differentiate implicitly between native and reference types. Native ones are always passed by value, reference types always by reference – well, Java reference, which actually resembles far more a C++ pointer (can be null, can be re-assigned) than a C++ reference. In Java, this happens implicitly, in C++, you need to be explicit about (on the other hand, you can have both behaviours for any type).
Java cast on (Java!) reference behaves like C++ dynamic_cast (on reference, i. e. throws, it won't return null on type mismatch).
Finally (concerning my polymorphism recommendation), in Java all functions are implicitly virtual, in C++, you again have to be explicit about (apply the virtual keyword, see above).
You are slicing your SpeedDataRoad object. Unlike Java objects, which have pointer/reference semantics, C++ objects have value semantics. That means, in your example, currentRoad is a Road, not a SpeedDataRoad. It is a copy of the Road part of whatever SppedDataRoad is created in your ....
To work with polymorphism is C++ you need to use references or pointers. That is, the following will not work because currentRoad is not a SpeedDataRoad:
double foo(Road currentRoad)
{
//...
return ((SpeedDataRoad)currentRoad).getSpeedProfileTime(currentTime, isRightDirection);
}
int main()
{
SpeedDataRoad road;
foo(road);
}
While the following will work because currentRoad references a SpeedDataRoad:
double foo(Road& currentRoad)
// ^---------------- Pass by reference now
{
//...
return dynamic_cast<SpeedDataRoad&>(currentRoad).getSpeedProfileTime(currentTime, isRightDirection);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Using C++-style cast and casting reference to reference
}
int main()
{
SpeedDataRoad road;
foo(road);
}
In the first example, currentRoad is a copy of the Road part of road, while in the second example currentRoad is a reference to road.
You should also avoid C-style casts in C++. In this instance, it would be better to use dynamic_cast<SpeedDataRoad&>(currentRoad) or, if you're absolutely sure currentRoad will always be a reference to a SpeedDataRoad object, static_cast<SpeedDataRoad&>(currentRoad). The former will do runtime type checking and throw an exception if currentRoad isn't a reference to a SpeedDataRoad while the latter will avoid the (small) overhead of doing runtime type checking, but will result in undefined behavior if currentRoad isn't a reference to a SpeedDataRoad.
That's called a downcast and not an upcast - the straightforward way to this by a dynamic_cast:
if (SpeedDataRoad* sdroad = dynamic_cast<SpeedDataRoad*>(¤tRoad); sdroad != nullptr) {
duration = sdroad->getSpeedProfileTime(currentTime, isRightDirection);
}
If you want to check inside a function if you can downcast a pointer/refernce into a child, you need to use dynamic cast.
void foo(Road* road){
SpeedDataRoad* child{nullptr};
if(child = dynamic_cast<SpeedDaraRoad*>(road){
// Do something with SpeedDataRoad
} else {
// road is not an instance of SpeedDataRoad
}
}
You can also use dynamic_cast with references, like so
cppSpeedDataRoad& child = dynamic_cast<SpeedDataRoad&>(reference_to_road);
But be carefull, as if the cast fails, std::bad_cast will be throw.
In C++, we try not to use C-style casting. (typename)object.
Instead, there are 4 types of type-casting.
static_cast<typename*>(pointer) static_cast<typename>(value): Upcasting of pointers and type-casting for value types
dynamic_cast<typename*>(pointer): Safe-downcasting of pointers (the one you should use). It does a runtime check for upcasting, hence, there is runtime cost.
const_cast<...>(...): Constant type
reinterpret_cast<typename*>(pointer) reinterpret_cast<typename>(value): Similar to C-style cast.
For objects (stack allocated), I rarely use casting. Because naturally objects in C++ has their own size, casting may change their size.
I have several structs:
struct Token
{
//some content
}
Then follows a bunch of structs that inherit from Token:
struct A : public Token{
//Stuff
}
.
.
.
struct Z : public Token{
//Other stuff
}
I have a vector std::vector filled with subclasses A through Z and my program crashes when I try to cast any element in the the vector to the subclass. I'm casting by doing the following:
A subclass = *((A * ) &vector[0]);
What am i doing wrong?
You should use dynamic_cast when casting pointers from one type to another in your use case.
The one you are using is a C style cast and I strongly suggest you to go with a dynamic_cast.
So your code should look something like:
if(dynamic_cast<A *>(vector[0]))
A subclass = *(dynamic_cast<A *>(vector[0]));
When a dynamic_cast fails it will return a NULL pointer and you should take care of it appropriately.
Refer dynamic_cast and static_cast in C++ for more information.
Additionally When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used? will help you understand a lot more types of casts.
A meaningful usage would be
A &subclassref = vector[0]);
In above line, no new object is created.
BTW what is the type of your vector and what exactly do you want to achieve? If you store objects of type A to Z in a single vector, it may at some point of time suffer object slicing.
This answer may be wrong because I'm making a guess as to how you have filled the std::vector<>.
You simply cannot put objects of subclasses into an std::vector<Base>. All objects in an std::vector<Base> are precisely of type Base. If you try something like this:
std::vector<Base> myVec;
myVec.push_back(Derived1(...));
you first construct an object of class Derived1 which is subsequently spliced into an object of class Base, i. e. a new object of class Base is copy-constructed from the derived object. Only this copy constructed base class object ends up in the std::vector<>.
If you want to have an std::vector<> of polymorphic objects, you must use a pointer type as the template argument (and consequently allocate the contained objects with new).
I have two classes. The superclass is a "Component" class, and the subclass is a "Transform" class.
The framework I'm using has a function that returns a list of components of a certain type. However, the list will return them as Component, since the type isn't restricted to a specific subclass (however it's the way I'm using it).
So, in the following scenario, I know that all the returned components will be of the Transform subclass. What I'm doing is I'm iterating over the list and then casting each component to Transform. Here is my code:
std::list<Cistron::Component*,std::allocator<Cistron::Component*>> playerTransforms = objectManager->getComponents(player,"Transform");
std::list<Cistron::Component*>::iterator playerComponentIterator = playerTransforms.begin();
for (playerComponentIterator; playerComponentIterator != playerTransforms.end(); playerComponentIterator++)
{
Transform *tmpTransform = static_cast<Transform*> (*playerComponentIterator);
std::cout << tmpTransform->x ;
std::cout << tmpTransform->y ;
}
How efficient is this? I'm quite new to C++, so I have no idea if there's a better way of doing this.
This isn't a good design, your compiler should generate a warning in this case. Normally, you should upcast your pointer using dynamic_cast. This cast has some runtime cost - aproximately the same as virtual method call but it will generate exception if you try to cast incompatible pointers.
Try to redesign your app to eliminate this code. You should only call virtual methods of the Component class, you shouldn't cast pointer to Component to pointer to Transform. This thing indicate bad design.
One possible desigion is to make getComponents a template method to eliminate cast:
template<class T>
list<T*> getComponents(Player* player, std::string name) {
...
}
or maybe just this:
list<Transform*> getTransfromComponents(Player* player) {...}
In a case when you can't refactor this code, you can always transform your list:
list<Component*> rlist = ...
list<Transform*> llist;
// Upcast all
transform(rlist.begin(),
rlist.end(),
back_inserter(llist),
[](Component* r) {
return dynamic_cast<Transform*>(r);
});
// Remove all null values
llist.remove(nullptr);
The std::list is usually implemented as double-linked list, which means that elements are scattered through the memory, which means that iterating through it is slow. Check: Why is it so slow iterating over a big std::list?
But what I would worry more about is the use of reflection:
objectManager->getComponents(player,"Transform");
that might actually be the real bottleneck of this piece of code.
In C++, I have a array pointer of objects like this:
vector<Articulation*> artic;
I have the next problem. When I send that vector to another class like &artic. So I have the pointer and not all the array duplicated. The problem is the next. In the new class, i have a ponter of array pointer objects
vector<Articulation*>* pArtic;
In the new class I do pArtic[i]->move(). The method is implemented in Articulation. When I do the method mov(), QT tell me that the type std::vector<_Ty> dont have an operator ->. That is because, I think, I cant access to the Articulation objects and I am trying to do move() over a vector.
Anyone knows what I must do to acces to the Articulation objects and do the move() method?
Example:
Class A:
vector<Articulation*> artic;
void A::initVector(){...}
void A::sendInfoToB(){
B nuevo();
B.send(&artic);
}
Class B:
vector<Articulation*>* pArtic
void B::send(vector<Articulacion*>* art){
pArtic=art;
}
void B::sendToC()
{
C nuevo();
C->sendTheLast(pArtic);
}
Class C:
void C::sendTheLast(vector<Articulation*>* artic)
{
string data=artic[i]->move();
//Move returns a String
}
That is the example.
The problem is, that you are calling the method move() of the i-th position of pArtic, which is a pointer to a vector of pointers. What you want to do is calling the method move of the pointer at the position i of the vector.
(*pArtic)[i]->move()
that is what you want to do, but care, this is not really safe I guess...
a better way would be to give away only the reference artic by expecting a vector<>& reference, not a pointer.
Store QT objects directly on containers (unless there is a real need of using pointers). This is because QT implements implicit sharing and COW (Copy-On-Write) which eradicates copy-overhead of containers everytime you pass them across. By passing the containers either by value or reference as need be, makes the interface simpler and easy to use.
Again, using raw-pointers in C++ is always dangerous when you have better mechanisms (like smart pointers). Smart pointers makes your program exception safe while managing the life of raw pointers.
I'm not a very experienced c++ coder and this has me stumped. I am passing a object (created elsewhere) to a function, I want to be able to store that object in some array and then run through the array to call a function on that object. Here is some pseudo code:
void AddObject(T& object) {
object.action(); // this works
T* objectList = NULL;
// T gets allocated (not shown here) ...
T[0] = object;
T[0].action(); // this doesn't work
}
I know the object is passing correctly, because the first call to object.action() does what it should. But when I store object in the array, then try to invoke action() it causes a big crash.
Likely my problem is that I simply tinkered with the .'s and *'s until it compiled, T[0].action() compliles but crashes at runtime.
The simplest answer to your question is that you must declare your container correctly and you must define an appropriate assigment operator for your class. Working as closely as possible from your example:
typedef class MyActionableClass T;
T* getGlobalPointer();
void AddInstance(T const& objInstance)
{
T* arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **objects**
//whose first element we don't mind losing
//**copy** the instance we've received
arrayFromElsewhere[0] = objInstance;
//now invoke the action() method on our **copy**
arrayFromElsewhere[0].action();
}
Note the signature change to const reference which emphasizes that we are going to copy the original object and not change it in any way.
Also note carefully that arrayFromElsewhere[0].action() is NOT the same as objInstance.action() because you have made a copy — action() is being invoked in a different context, no matter how similar.
While it is obvious you have condensed, the condensation makes the reason for doing this much less obvious — specifying, for instance, that you want to maintain an array of callback objects would make a better case for “needing” this capability. It is also a poor choice to use “T” like you did because this tends to imply template usage to most experienced C++ programmers.
The thing that is most likely causing your “unexplained” crash is that assignment operator; if you don't define one the compiler will automatically generate one that works as a bitwise copy — almost certainly not what you want if your class is anything other than a collection of simple data types (POD).
For this to work properly on a class of any complexity you will likely need to define a deep copy or use reference counting; in C++ it is almost always a poor choice to let the compiler create any of ctor, dtor, or assignment for you.
And, of course, it would be a good idea to use standard containers rather than the simple array mechanism you implied by your example. In that case you should probably also define a default ctor, a virtual dtor, and a copy ctor because of the assumptions made by containers and algorithms.
If, in fact, you do not want to create a copy of your object but want, instead, to invoke action() on the original object but from within an array, then you will need an array of pointers instead. Again working closely to your original example:
typedef class MyActionableClass T;
T** getGlobalPointer();
void AddInstance(T& objInstance)
{
T** arrayFromElsewhere = getGlobalPointer();
//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **pointers**
//whose first element we don't mind losing
//**reference** the instance we've received by saving its address
arrayFromElsewhere[0] = &objInstance;
//now invoke the action() method on **the original instance**
arrayFromElsewhere[0]->action();
}
Note closely that arrayFromElsewhere is now an array of pointers to objects instead of an array of actual objects.
Note that I dropped the const modifier in this case because I don’t know if action() is a const method — with a name like that I am assuming not…
Note carefully the ampersand (address-of) operator being used in the assignment.
Note also the new syntax for invoking the action() method by using the pointer-to operator.
Finally be advised that using standard containers of pointers is fraught with memory-leak peril, but typically not nearly as dangerous as using naked arrays :-/
I'm surprised it compiles. You declare an array, objectList of 8 pointers to T. Then you assign T[0] = object;. That's not what you want, what you want is one of
T objectList[8];
objectList[0] = object;
objectList[0].action();
or
T *objectList[8];
objectList[0] = &object;
objectList[0]->action();
Now I'm waiting for a C++ expert to explain why your code compiled, I'm really curious.
You can put the object either into a dynamic or a static array:
#include <vector> // dynamic
#include <array> // static
void AddObject(T const & t)
{
std::array<T, 12> arr;
std::vector<T> v;
arr[0] = t;
v.push_back(t);
arr[0].action();
v[0].action();
}
This doesn't really make a lot of sense, though; you would usually have defined your array somewhere else, outside the function.