I am learning c++.
I would like to try to downcast a interface class ; although I have learned down casting may result from a bad programming design.
Some sites say "use dynamic_cast to check validity of down casting". However, in my case, I don't need to check the validity because I can guarantee it is a down casting from a base class to a derived class. I tried dynamic_cast and static_cast in the following example code. And they works well.
Can I use static_cast when I can guarantee it is a valid down casting?
Example code :
struct Parent_Interface {
virtual ~Parent_Interface() {};
virtual void print(void) = 0;
};
struct Child : public Parent_Interface {
virtual ~Child() {};
void print(void) override {
std::cout << "Child::print()." << std::endl;
}
};
void StaticDownCastToChild(Parent_Interface& parent_interface) {
auto& child0 = static_cast<Child&>(parent_interface);
std::cout << "StaticDownCastToChild : ";
child0.print();
}
void DynamicDownCastToChild(Parent_Interface& parent_interface) {
auto& child0 = dynamic_cast<Child&>(parent_interface);
std::cout << "DynamicDownCastToChild : ";
child0.print();
}
void test_static_cast_down_cast(void) {
Child c;
StaticDownCastToChild(c);
DynamicDownCastToChild(c);
}
Output of executing test_static_cast_down_cast().
StaticDownCastToChild : Child::print().
DynamicDownCastToChild : Child::print().
Some sites say "use dynamic_cast to check validity of down casting". However, in my case, I don't need to check the validity because I can guarantee it is a down casting from a base class to a derived class.
Correct.
Can I use static_cast when I can guarantee it is a valid down casting?
Yes.
In fact, you should, as it is "free". dynamic_cast often involves some runtime overhead.
However, you may wish to put a dynamic_cast in an assert alongside it, for good measure. Remember that this will have no effect on your release build, but may aid you during debugging if something goes horribly wrong. Some of the most satisfying moments of my career have involved a well-placed assert firing unexpectedly, resulting in a very quick bug-fixing process; the alternative can be months of pain and guesswork!
Some sites say...
Don't mind what some sites say. The standard (working draft) says:
An lvalue of type “cv1 B”, where B is a class type, can be cast to type “reference to cv2 D”, where D is a class derived from B, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1.
Also, it contains an example that is almost the same you are asking for:
struct B { };
struct D : public B { };
D d;
B &br = d;
static_cast<D&>(br); // produces lvalue to the original d object
Therefore I would say that yes, you can do that.
There are plenty of uses for such a cast. As an example, CRTP idiom is a case where you know exactly what's the type of the derived class and you don't want to check if the cast is valid through the use of dynamic_cast. Your case is probably another one of those (it's hard to say without the original code).
Can I use static_cast when I can guarantee it is a valid down casting?
Yes, you can. That said, situations where you know the cast will be valid but you can't specify the more-specific type (e.g. Child&) shouldn't come up very often. I can't think of a reason that you'd use Parent_Interface& instead of Child& when you know you're always passing the latter.
Related
example
struct B1{int x; void f(){x = 1;}};
struct D : B1{int x; void f(){B1::x = 2;}};
using Dmp = void(D::*)();
using B1mp = void(B1::*)();
int main()
{
Dmp dmp = &D::f;
D d;
(d.*dmp)(); // ok
B1mp b1mp = static_cast<B1mp>(dmp); // hm, well that's weird
B1 b1;
(b1.*b1mp)();
dmp = &B1::f; // ok
}
And this example will compile and run just fine, and no problem will arise. But wait, now I'm going to use D::x in D::f, and now -- anything can happen at runtime.
Yes, you can also static_cast a pointer to the base to a pointer to a derived.
static_cast<D*>( (B1*)0 )
But here you can use RTTI to check the types, or just use dynamic_cast if possible.
Yes, static_cast allows a number of things that might be used in "unsafe" ways, like converting void* to another object pointer type, converting Base* to Derived*, and this one.
Although static_cast can be thought of as "relatively safe" compared to reinterpret_cast and const_cast, it's still a cast. And like all casts, it represents a request to ignore some of the type system's safety requirements, with the programmer then responsible for using it carefully and correctly.
In
void f(B *b) {
static_cast<D*>(b)->d_method();
b->static_cast<void (B::*)()>(&D::d_method)();
}
you assume that b is a D to exactly the same degree in each case. Being able to cast the pointer-to-member allows a caller to nominate any function from any derived class when passed to a function that expects a pointer-to-member for the base.
#include <iostream>
class Base {
};
class Derived : public Base {
};
int main() {
Base* bptr = new Derived();
Derived* dptr = static_cast<Derived*>(bptr);
std::cout << dptr << std::endl;
}
In the above code, I should be using dynamic_cast but am using
static_cast incorrectly. static_cast should never be used while
downcasting, since compiler has no way to determine we are doing
cast correctly.
Why isn't this a compile error ? I am using gcc 4.9.2. Do you guys
think this is a bug in the compiler, or does C++ standards allow such code ?
Edit: Thanks for the responses. Actually, Base class above is polymorphic
i.e. it has virtual functions, but I left them out for this example. I should
have thrown in a virtual destructor in the Base to make it clear that it
was polymorphic - my bad.
In the above code, I should be using dynamic_cast but am using static_cast incorrectly. static_cast should never be used while downcasting, since compiler has no way to determine we are doing cast correctly.
Ironically, the dynamic_cast would actually be the ill-formed cast here, since your types are not polymorphic.
That said, static_cast can certainly be used to downcast. You are correct that the compiler cannot do type-checking, but there are many situations in which you have a Base* and know that it points to a Derived*, so you can just manually do the cast. One very common case is CRTP:
template <class Derived>
class Base {
Derived& self() { return *static_cast<Derived*>(this); }
// ...
};
class Foo : Base<Foo> { ... };
Base<T> is always a T, so that downcast is safe.
The advantage of static_cast over dynamic_cast is that static_cast is free but dynamic_cast is expensive. The C++ mantra is don't pay for what you don't need.
static_cast < new_type > ( expression )
If new_type is a pointer or reference to some class D and the type of
expression is a pointer or reference to its non-virtual base B,
static_cast performs a downcast. This downcast is ill-formed if B is
ambiguous, inaccessible, or virtual base (or a base of a virtual base)
of D. Such static_cast makes no runtime checks to ensure that the
object's runtime type is actually D, and may only be used safely if
this precondition is guaranteed by other means, such as when
implementing static polymorphism. Safe downcast may be done with
dynamic_cast.
Source (Explanation item 2)
You are using static_cast perfectly correctly. You are right, the compiler can in the general case not know whether the cast is correct, but static_cast is exactly there for this scenario.
You cannot use dynamic_cast here because that cast is for polymorphic classes (those which have a virtual member function). These classes carry run-time information; that information allows the code to choose the correct implementation of that function in the actual type of the object pointed to. This type information in the object can be used by the cast function to determine whether the type conversion is possible, and then indeed perform the conversion properly (which can be tricky with multiple and virtual inheritance).
Classes without virtual functions, like your example classes, do not carry this run time information, and dynamic_cast cannot be used to cast to a more derived type. (It can still be used to cast to the same type or to a base class, i.e. it can be used for conversions which do actually not need a cast.)
I have a cpp code where in class c is derived from class b and class b is derived from class a.
Now class b has some public data member. So I am creating a instance of class c on heap passing its pointer to another class as pointer to a and there it is downcasting that pointer to pointer of class b and then printing public variables of class b.
Is this a valid downcasting. I am asking because just change of compiler has broken this working code.
I am including below code snippet which captures problem I am having.
#include <iostream>
using namespace std;
class grand
{
};
class parent : public grand
{
public : parent(){i=0;}
int i;
parent(int j){ i = j;}
void set(int j){i = j;}
};
class child : public parent{
public: child(){};
};
void print ( grand* ptr)
{
parent *p = (parent*) ptr;
std::cout << std::endl << p->i << std::endl;
}
int main() {
// your code goes here
child c;
c.set(9);
print(&c);
return 0;
}
Thanks
Is this a valid downcasting.
Yes. Your cast internally applies static_cast, which, according to §5.2.9/11, will give you the right result. If the argument for ptr doesn't point to a parent, the result of the cast is undefined - and so would the execution of the following code be.
Downcasting of polymorphic types in C++ works via dynamic_cast. Your grand class above isn't polymorphic - you have to add at least a virtual destructor to grand to make it polymorphic. Otherwise you'll get a compiler error with the following code.
parent *p = dynamic_cast<parent*>(ptr); // Once grand is polymorphic...
And check whether the result, p, is non-zero. Only this method reveals (at runtime) whether the cast worked! All others either invoke undefined behavior or undefined, non-zero values.
Some notes:
Downcasting is almost always a sign of bad design. Avoid it if possible, using - for example - virtual (print) functions.
print should take a pointer to const since it doesn't modify any data members.
Your code, as written, is in fact valid, but there are a bunch of observations I'd like to make. Note that it's valid only because the object you pass to print is a parent or further derived class.
Then note that since you have to cast it the print function it's much safer to just change the function signature to take aparent instead of a grand and then you don't have to worry about the casting.
Then note that a likely cause of your problem is that in the file that does the cast, the compiler doesn't see the relationship between grand and parent so your C-style cast falls back to reinterpret_cast which is not what you want. If you can't change the signature of print at least change the cast to static_cast (or possibly dynamic_cast, but you can't do that in your example because the classes aren't polymorphic) so that the compiler will fail to compile when it can't see the class relationship.
Instead of a C-style cast you should apply a dynamic_cast or a at least a static_cast if you compile without RTTI (runtime type information) for some reason.
Your C-style cast is the same as a reinterpret_cast, which essentially interprets the memory pointed to as if an object of type parent would have been constructed there. But, every compiler may have a different memory layout of derived classes, thus that may work in some circumstances but there's no guarantee.
In C++, assume following class hierarchy:
class BaseClass { };
class ChildClass : public BaseClass { };
Further assume factory classes for these two classes with a common, templated base class:
template<typename T>
class Factory {
public:
virtual T* create() = 0;
};
class BaseClassFactory : public Factory<BaseClass> {
public:
virtual BaseClass* create() {
return new BaseClass(&m_field);
}
private:
SomeClass m_field;
};
class ChildClassFactory : public Factory<ChildClass> {
public:
virtual ChildClass* create() {
return new ChildClass(&m_field);
}
private:
SomeOtherClass m_field; // Different class than SomeClass
};
Note that the size/internal structure of ChildClassFactory and BaseClassFactory is different due to their different fields.
Now, if a have an instance of ChildClassFactory (or Factory<ChildClass>), can I safely cast it to Factory<BaseClass> (via reinterpret_cast)?
Factory<ChildClass>* childFactory = new ChildClassFactory();
// static_cast doesn't work - need to use reinterpret_cast
Factory<BaseClass>* baseFactory = reinterpret_cast<Factory<BaseClass>*>(childFactory);
// Does this work correctly? (i.e. is "cls" of type "ChildClass"?)
BaseClass* cls = baseFactory->create();
I know that you can't always cast templated classes this way, but in this special case a cast should be safe, shouldn't it?
I've tested it with Visual C++ 2010 and it does work. My question now is whether this is portable to other compilers?
Update: Since there has been some confusion let me clarify some more what's (supposed to be) important in my example:
ChildClass is a child class of BaseClass
A user of Factory<BaseClass> doesn't know what child class of BaseClass will be created. All he knows is that BaseClass is created.
Factory<T> has no fields of its own (other than the vtable).
Factory::create() is virtual
No, it is not. You may not use the result of a reinterpret_cast other than to cast stuff back, except for a few special cases:
ISO14882:2011(e) 5.2.10-7:
An object pointer can be explicitly converted to an object pointer of
a different type.70 When a prvalue v of type “pointer to T1” is
converted to the type “pointer to cv T2”, the result is static_cast(static_cast(v)) if both T1 and T2 are standard-layout
types (3.9) and the alignment requirements of T2 are no stricter than
those of T1, or if either type is void. Converting a prvalue of type
“pointer to T1” to the type “pointer to T2” (where T1 and T2 are
object types and where the alignment requirements of T2 are no
stricter than those of T1) and back to its original type yields the
original pointer value. The result of any other such pointer
conversion is unspecified.
To make a possible failure scenario more clear, consider multiple inheritance, where using a static_cast or dynamic_cast would sometimes adjust the pointer value, but reinterpret_cast will not. Consider casting in this example from A* to B*:
struct A { int x; };
struct B { int y; };
struct C : A, B { };
To understand how your code fails in a different way too, consider how most compilers implement the virtual function call mechanism: With virtual pointers. Your instance of ChildClassFactory will have a virtual pointer, pointing to the virtual table of ChildClassFactory. Now when you reinterpret_cast this beast, it just happens to "work" incidentally, because the compiler expects some virtual pointer, pointing to a virtual table that will have the same/similar layout. But it will still contain the values pointing to the ChildCLassFactory virtual functions, thus these functions would be called. All of this is long after invoking undefined behaviour. It is as if you are jumping with a car into a large canyon and thinking "hey, everything is driving fine" just because you have not hit the ground yet.
No, reinterpret_cast is only to be used for lowlevel code since it will not perfrom the correct address manipulation. Use static_cast or dynamic_cast instead,
Why do you want two factories this does not fit in the GoF factory pattern.
reinterpret_cast is not the way to do it since it is slow (runtime checks) and is not a nice OO design (you want to use the polymophisme build into the language).
Instead make constructors in the factory class that produces the types you are after and then have these call the constructor of the individual types.
The factory pattern allows you to be by ignorant of changes in your implementaion, which is a good thing since you minimize your dependencies, and allows for easier maintainance in the future of the code.
I've ticked the original answer above (to give him the credit), but I thought I'd sum up what I've learned here.
So, the basic problem is that it's not defined how dispatching virtual calls must be implemented.
This means that the data structure(s) that are internally used for virtual call dispatching (e.g. vtables) may or may not be bit compatible among template instantiations created from the same template.
I copy the following text from the book More Effective C++.
Item 31: Making functions virtual with respect to more than one object.
class GameObject { ... };
class SpaceShip: public GameObject { ... };
class SpaceStation: public GameObject { ... };
class Asteroid: public GameObject { ... };
The most common approach to double-dispatching returns us to the unforgiving world of virtual function emulation via chains of if-then-elses. In this harsh world, we first discover the real type of otherObject, then we test it against all the possibilities:
void SpaceShip::collide(GameObject& otherObject)
{
const type_info& objectType = typeid(otherObject);
if (objectType == typeid(SpaceShip)) {
SpaceShip& ss = static_cast<SpaceShip&>(otherObject);
process a SpaceShip-SpaceShip collision;
}
else if (objectType == typeid(SpaceStation)) {
SpaceStation& ss =
static_cast<SpaceStation&>(otherObject);
process a SpaceShip-SpaceStation collision;
}
...
}
Here is the question:
Q1> Why we use static_cast here rather than obvious dynamic_cast?
Q2> Are they same in this case?
thank you
// updated //
In fact, I am more interested in question 2.
For example,
class base {};
class subclass : public base {};
base *pSubClass = new subclass;
subclass *pSubClass1 = static_cast<subClass*> (pSubClass);
// does the static_cast do the job correctly in this case although I know we should use dynamic_cast here?
For the record, here is the idiomatic way of doing that:
void SpaceShip::collide(GameObject& otherObject)
{
if (SpaceShip* ss = dynamic_cast<SpaceShip*>(&otherObject)) {
// process a SpaceShip-SpaceShip collision;
}
else if (SpaceStation* ss = dynamic_cast<SpaceStation*>(&otherObject)) {
// process a SpaceShip-SpaceStation collision;
}
// ...
}
It's shorter, exhibits identical performance characteristics, and again, most importantly, is idiomatic C++ that won't make other programmers scratch their heads and wonder what the point is.
EDIT (in response to the OP's edit):
Yes, that is well defined behavior. Here's what the C++03 standard says, §5.2.9/8:
An rvalue of type “pointer to cv1 B”, where B is a class type, can be converted to an rvalue of type “pointer to cv2 D”, where D is a class derived from B, if a valid standard conversion from “pointer to D” to “pointer to B” exists, cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is not a virtual base class of D. The null pointer value is converted to the null pointer value of the destination type. If the rvalue of type “pointer to cv1 B” points to a B that is actually a sub-object of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.
You've already verified the types yourself, so you don't need to use dynamic_cast. Dynamic_cast will check the types for you automatically.
Why they chose to implement it this way, instead of the more traditional dynamic_cast I can't say, but the behavior of the two options is not necessarily the same. As written, that code only considers the actual type of the parameter, while dynamic_cast considers where the parameter falls in an inheritance tree. Consider:
struct Base { virtual ~Base() { } };
struct Intermediate : Base { };
struct Derived : Intermediate { };
int main() {
Intermediate i;
Base* p_i = &i;
Derived d;
Base* p_d = &d;
assert(typeid(*p_i) == typeid(Intermediate)); //1
assert(dynamic_cast<Intermediate*>(p_i)); //2
assert(typeid(*p_d) == typeid(Intermediate)); //3
assert(dynamic_cast<Intermediate*>(p_d)); //4
}
(1) and (2) both pass their assertions, but (3) fails while (4) succeeds. p_d points to a Derived object, so type_id yields information for a Derived object, which will not compare equal to the information for an Intermediate object. But Derived derives from Intermediate, so dynamic_cast will happily convert a pointer to Derived to a pointer to Intermediate.
To put it in terms used in the original question, if otherObject is a Frigate, which derives from SpaceShip, it will not use the "spaceship<->spaceship" collision routine. There's a good chance this is not the intended behavior; you might want Frigate to use that code, but instead you have to manually add an explicit check for that new type.
Of course, if you're only checking against types that are never inherited from, this difference goes away. Or if you just don't want polymorphic behavior (although that would make the heading somewhat misleading). In that case, this might be more performant, but that's a giant implementation detail and I certainly wouldn't put money on it in practice.
Another small, and largely inconsequential, difference occurs if the types are not polymorphic. In my above code, if you remove the virtual destructor from Base, (2) and (4) now exhibit undefined behavior. (1) and (3) remain well defined, but are now worthless; both will fail because typeid(*p_i) will yield information about Base rather than Intermediate like it used to.
This seems like a pretty solid answer. Basically static cast is faster but doesn't do runtime type checking.
Some compilers will generate codes that throws std::bad_cast if dynamic_cast fails. So in this case the two approaches are different. Using dynamic_cast may looks like
try {
SpaceShip& ship = dynamic_cast<SpaceShip&>(otherObject);
// collision logic
return;
} catch (std::bad_cast&) {}
try {
SpaceStation& station = dynamic_cast<SpaceStation&>(otherObject);
// collision logic
return;
} catch (std::bad_cast&) {}
that looks really bad.
First, I think it's important to note that Myers is presenting this code as the first strawman solution for double dispatch before moving on to superior solutions that are not dependent on RTTI.
To answer the second question first, yes, this is equivalent to implementations using dynamic_cast.
static_cast is used here because we have already established that the object is of the targetted type, and thus don't need to pay for run-time checking again.
So why not use dynamic_cast in the first place?
My suspicion is that Myers wrote it this way because this was going to be a chain of an indefinite number of if () checks. He could have done something like #ildjarn suggests, but that would have involved declaring a new variable for every type he wanted to check it against. My suspicion is he just liked the aesthetics of what he put up better.
Maybe I'm mistaken, but ... my understanding is that all rtti implementations involve some kind of lookup/search to find the type of an object passed to dynamic_cast or typeinfo.
Barring quantum effects, this search must take a measurable number of cycles to complete and, in the OP's code, the search result is cached, while in the dynamic_cast examples the search is repeated in each conditional.
Therefore the cached version must be faster. Keeping in mind caveats about premature optimization, I think it is also easy on the eye.
Nicht war?
PS: Tried this and it doesn't work. Hmmm. Anybody suggest why?