1

Could you please explain work of static_cast?

Why this code doesn't work?

D another_d = static_cast<D>(br); // ERROR - no matching function for call to ‘D::D(B&)’

My code

#include <bits/stdc++.h>

using namespace std;

struct B {
    int m = 0;
    void hello() const {
        std::cout << "Hello world, this is B!\n";
    }
};

struct D : B {
    void hello() const {
        std::cout << "Hello world, this is D!\n";
    }
};

int main(){
    D d;
    B br = d; // upcast via implicit conversion
    br.hello(); // Hello world, this is B!
    // D another_d = static_cast<D>(br); // ERROR - no matching function for call to ‘D::D(B&)’
    D& another_d = static_cast<D&>(br); // OK
    another_d.hello(); // Hello world, this is D!
}
swor
  • 413
  • 8
  • FYI: [Why should I not #include ?](https://stackoverflow.com/q/31816095/7478597) (A simple `#include ` would have worked as well and makes your sample portable.) ;-) – Scheff's Cat Jan 24 '21 at 15:06

1 Answers1

3
B br = d; // upcast via implicit conversion

This is object slicing. br is an instance of B and copies only the B part of d. (This implies down-casting of d to B& which the compiler can do implicitly because D is derived from B.)

D another_d = static_cast<D>(br);

This is the attempt to create an instance of D from an instance of B.
While D is also a B (due to inheritance) the opposite is not true. So, there is nothing the compiler can do implicitly.

To make this working, a constructor D(B&) has to be defined.

To illustrate this: D might have additional member variables which cannot copied from B, and this is what such constructor had to handle in any way.

D& another_d = static_cast<D&>(br); // OK

This is not really OK. It might (seem to) work as D doesn't contain additional member variables.

br is an instance of B (not of D). "Faking" a reference to D is actually a lie but doing this explicitly (in code) makes the compiler silent. However, it's still wrong.

Scheff's Cat
  • 16,517
  • 5
  • 25
  • 45
  • thank you, after this answer it seems that static_cast is really useful for inductrial programming only for void* casting, isn't it? – swor Jan 24 '21 at 15:07
  • 1
    @swor `static_cast` is the rescue in complex production code where clean programming sometimes cannot be achieved with reasonable effort. But, it has always to be used with caaare. ;-) – Scheff's Cat Jan 24 '21 at 15:09
  • @swor Imagine, you have an instance of `D` but it is stored as pointer to `B` (`B*`) or reference to `B` (`B&`). And for any reason, you cannot change this detail. At some point, you get a pointer/reference to `B` but you know for sure that it actually addresses a `D`. The first approach should be to use `virtual` member functions but this is not the solution in any case (and comes with additional costs). In this case, a `static_cast`/`static_cast` might be the rescue. Maybe, another design would prevent this but might be too much effort for a specific issue. – Scheff's Cat Jan 24 '21 at 15:17