2

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?"

4
  • 3
    please give example what didn't work when you "tried it with non-pointer variables" Commented Apr 3, 2014 at 17:28
  • Generally, having to cast from a parent to a child is a code smell. You may want to rethink your design. See if you can accomplish the same thing using virtual member functions. Commented Apr 3, 2014 at 17:35
  • @Dima Often the code has been in place for many years, so rethinking the design requires rewriting thousands (if not tens of thousands) of lines of code. So rethinking is often not an option. I have run into this exact problem that K_U has where pointers and references cast fine, but casting non-pointer variables will not compile on code that CANNOT be rethought or rewritten. And I was hoping someone on SO would provide some light on the subject. Commented Nov 14, 2018 at 6:39
  • @K_U Take a look at stackoverflow.com/questions/53294643/…. It helped me at least. Commented Nov 14, 2018 at 20:32

4 Answers 4

5

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 declaration T t(e); is well-formed, for some invented temporary variable t (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?).

Sign up to request clarification or add additional context in comments.

4 Comments

Not the most interesting use of static_cast that you cited though, because here static_cast is not necessary to achieve the functionality. A much more interesting use is static_cast<T>(e) when decltype(e) _(t); is a valid expression.
I like this answer the best so far because it quotes the standard. If the OP reads that carefully, then he can probably figure out why his attempt to use static cast failed.
Hi, i tried it the other way...i tried to assign a value to a child instance from a parent instance.
this makes no sense as child is "bigger" object than parent
1

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.

1 Comment

Mark inheritance as public for derived class because by default is private and in the way that you present this code doesn't work (class derived: public base { int y; };).
0

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.

1 Comment

Also I'm going to add on that whenever you have to do this you've pointed out to yourself where you've got bad design!
0

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.

1 Comment

Yes, it is also possible to use static_cast with references. Thank you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.