Why use static_cast rather than dynamic_cast?

I will copy the following text from the book More Effective C ++.

Paragraph 31: Performing functions virtual with respect to several objects.

class GameObject { ... };
class SpaceShip: public GameObject { ... };
class SpaceStation: public GameObject { ... };
class Asteroid: public GameObject { ... };

The most common dual dispatch approach takes us back to the inexorable world of emulating virtual functions through if-then-elses chains. In this harsh world, we first discover the real type of otherObject, then test it for 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 are we using static_cast here and not the obvious dynamic_cast?

Q2> Are they the same in this case?

Thank you

// updated //

Actually, I'm more interested in question 2.

For instance,

class base {};
class subclass : public base {};

base *pSubClass = new subclass;

subclass *pSubClass1 = static_cast<subClass*> (pSubClass); 

// does static_cast do the correct job in this case, although I know that dynamic_cast should be used here?

+3
7

:

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;
    }

    // ...
}

, , , , - ++, , .


EDIT ( OP):

, . ++ 03, §5.2.9/8:

" cv1 B", B , rvalue " cv2 D", D - B, " D" " B", cv2 cv-, cv-, cv1 B D. . rvalue " cv1 B" a B, - D, D. undefined.

+7

, dynamic_cast. Dynamic_cast .

+3

, dynamic_cast , . , , dynamic_cast , . :

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) (2) , (3) , (4) . p_d Derived, type_id Derived, Intermediate. Derived Intermediate, dynamic_cast Derived Intermediate.

, , otherObject Frigate, SpaceShip, " ↔ ". , ; Frigate , .

, , , . ( ). , , , , .


, , , . , Base, (2) (4), undefined. (1) (3) , ; , typeid(*p_i) Base, Intermediate, .

+1

. , .

0

, std::bad_cast, dynamic_cast . , . dynamic_cast

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&) {}

.

0

-, , Myers , , RTTI.

, , dynamic_cast.

static_cast , , , , .

, dynamic_cast ?

, , if (). - @ildjarn, , . , , .

0

, , ... , rtti - /, , dynamic_cast typeinfo.

By prohibiting quantum effects, this search requires a measurable number of cycles, and in the OP code the search result is cached, and in the dynamic_cast examples the search is repeated in each conditional expression.

Therefore, the cached version should be faster. Keeping in mind the caveats regarding premature optimization, I think it is also easy on the eyes.

War Nicht?

PS: I tried this and it does not work. Hmmm. Does anyone tell me why?

0
source

All Articles