Reputation: 17762
I recently had a situation where i had to use static_cast to cast a parent class to a child class, because i knew the object instance was that child class. I knew this based on an if condition.
Something like this:
parent* foo;
child* bar;
if(foo is instance of child class)
bar = static_cast<child*>(foo)
My question is: Why does static_cast always require pointers? This did not work when i tried it with non-pointer variables. An exception seems to be primitive data types.
Is this because every pointer can be cast as a void*? Is that how static_cast works?
Edit: I forgot to mention that it works with references. So the question, as it is currently framed, is wrong. Reframing the question to "Why does static_cast require pointers or references?"
Upvotes: 2
Views: 3368
Reputation: 1109
In essence static_cast<>
always creates something new with type provided between the angle brackets. Consider:
class base { int x; };
class derived: public base { int y; };
Now the following code will not compile:
base *b;
derived *d = &static_cast<derived>(*b); // wrong
The reason is simple: this code tries to create new instance of derived
and pass a base
to its constructor. It would compile if derived
had the constructor for that. For example:
class derived: public base
{
int y;
derived(const base &){}
};
But now you have a temporary that is going to be deleted immediately.
Obviously you don't want to create new derived
instances here, but to reach the derived instance your base is part of. You need to create either a reference or a pointer to derived
when performing the cast, and not a whole new instance of it. The following is going to work:
derived d;
base *bp = &d;
base &br = d;
derived &dr = static_cast<derived &>(br);
derived *dp = static_cast<derived *>(bp);
Now both dr
and dp
point to the same d
above.
Upvotes: 1
Reputation: 29724
Why does static_cast always require pointers?
The operator static_cast
doesn't require pointers, nor references.
C++ Standard n3337 § 5.2.9/4:
Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form
static_cast<T>(e)
if the declarationT t(e)
; is well-formed, for some invented temporary variablet
(8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The expression e is used as a glvalue if and only if the initialization uses it as a glvalue.
parent* foo;
child* bar;
if(foo is instance of child class)
bar = static_cast<child*>(foo)
This did not work when i tried it with non-pointer variables.
For example? How you tried it? If you mean
child c;
parent p = static_cast<parent>( c);
then this is called slicing, what means p will only get those data from c which comes from parent class (how could object of class parent receive also child part, since child is addition to derived parent data?).
Upvotes: 5
Reputation:
Why does static_cast always require pointers?
Well, not always. As you pointed out, the following is possible:
int i = static_cast<int>(3.14);
static_cast
can also be used to convert between references, just like with pointers.
However, you have to take the following into account: When converting between two types, you can loose information. Suppose you have a class Animal
and another class Dog
that happens to inherit from it. What would this mean?
Dog d;
Animal a = static_cast<Animal>(d);
You're creating an Animal
out of a Dog
, but the Dog
's specific information will be thrown away. This is called slicing.
Casting between pointers usually just involves reinterpreting memory; the underlying object stays the same.
Upvotes: 0
Reputation: 7881
The reason is: it doesn't, it can be pointers or references. This has to do with the following problem:
struct Base
{
};
struct Derived : public Base
{
int A;
};
//sizeof(Base)==0
//sizeof(Derived)==4
Base B;
Derived X;
X.A = 10;
B=X;//what happens to Derived::A? There is no space to put it. This is called slicing.
Basically, you cannot make an INSTANCE of a based class with a derived class without risking slicing. But references/pointers are another matter. in that case, you are just interpreting how the memory pointed to is interpreted. Static cast doesn't actually do any operations in this case! Because of the way C++ classes are layed out (intentionally) everything that inherits from a Base class has t'she same memory layout from offset of 0 to sizeof(Base). Only after that do you add Derived stuff.
Upvotes: 0