1

i was just reading this question here https://stackoverflow.com/a/332086/2689696 and it tells that dynamic cast

You can use it for more than just casting downwards -- you can cast sideways or even up another chain. The dynamic_cast will seek out the desired object and return it if possible.

so what does this really mean and what are the limitations/ conditions under which this can happen.

and i assume this is what the statement means. And the cast happens and i get a segmentation fault too which is obvious.

#include <iostream>
class base
{
public:
    virtual void print () = 0;
};

class childa : public base
{
public:
    char c1;
    virtual void print ()
    {
        std::cout << "childa\n";
    }
    void printout()
    {
        std::cout << "childa out\n";
    }
};

class childb : public base
{
public:
    int c2;
    virtual void print ()
    {
        std::cout << "childb\n";
    }
    void printin()
    {
        std::cout << "childb in\n";
    }
    void printout()
    {
        std::cout << "childb out\n";
    }
};

int main()
{
    base* b = new childa;
    b ->print();
    dynamic_cast<childa*>(b)->printout();
    dynamic_cast<childb*>(b)->printout();   // cast happens here and the output is printed
    dynamic_cast<childa*>(b)->c1 = 'a';
    dynamic_cast<childb*>(b)->c2 = 2;   // segfault here
}

This is the output i get and a segfault occurs

childa
childa out
childb out

Process returned -1073741819 (0xC0000005) execution time : 5.844 s
Press any key to continue.

EDIT: Yes it was foolish of me not to check for null value. but i wanted to know more about the comment from the other question(Up/Down/Sideways)

Community
  • 1
  • 1
tejas
  • 1,795
  • 1
  • 16
  • 34
  • `b` does not point to a `childb`, so the cast fails. – juanchopanza Mar 18 '14 at 19:43
  • 2
    cross-casting occurs when you have: `class base1;` `class base2; /* not related to base1*/` `class derived : public base1, public base2` `base1 * b1instance = new derived; dynamic_cast(b1instance)` Essentially, to cross cast you need a pointer to some base, and you dynamically cast it to a pointer to some unrelated base in another heirarchy, but the underlying object actually does derive from both heirarchies. – YoungJohn Mar 18 '14 at 19:53

3 Answers3

5

You're hitting Undefined Behaviour here:

dynamic_cast<childb*>(b)->printout();

The cast actually fails (returns a null pointer). You never check the return value and call a member function through it. That's Undefined Behaviour and anything can happen. In your case, it seems that because the function does not access this in any way, it executes just fine even though invoked through a null pointer. But that's not guaranteed.


As for what a sideways cast (or cast up another chain) is, that needs a more complex inheritance hierarchy to demonstrate:

struct base1
{
  virtual ~base1() {}
};

struct base2
{
  virtual ~base2() {}
};

struct child1 : base1
{};

struct child2 : base2
{};

struct both : child1, child2
{};


int main()
{
  child1 *c1 = new both();
  static_cast<base1*>(c1);  // ok
  static_cast<both*>(c1);  // ok
  static_cast<child2*>(c1);  // compile-time error, unrelated types
  dynamic_cast<child2*>(c1);  // succeeds, because the object is actually of type `both`, i.e. derived from `child2`; cast sideways
  static_cast<base2*>(c1);  // compile-time error, unrelated types
  dynamic_cast<base2*>(c1); // succeeds, because the object is actually of type `both`, i.e. derived from `base2`; cast up another chain

  base1 *b1 = new child1();
  static_cast<child1*>(b1);  // ok
  static_cast<both*>(b1);  // compiles, but produces UB, as the object is not of correct type
  static_cast<base2*>(b1);  // compile-time error, unrelated types
  dynamic_cast<base2*>(b1);  // fails (returns null pointer), because the object is not actually derived from `base2`.
}
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
0

dynamic_cast<T*>(a) returns a not null T* if and only if *a is instance of T; otherwise, it returns NULL.

Invoking a method or attribute from a null pointer produces an undefined behavior.

ebasconp
  • 1,608
  • 2
  • 17
  • 27
0

The usefulness of dynamic_cast is in his answer. With this code

int main()
{
    base* b = new childa;
    b ->print();

    childa* testA = dynamic_cast<childa*>(b);
    if (testA)
    {
        //Here you can be sure that your object is right
        testA->printout();
        testA->c1 = 'a';
    }
    else
        std::cout << "Error casting b to testA" << std::endl;

    childb* testB = dynamic_cast<childb*>(b);
    if (testB)
    {
        //Here you can be sure that your object is right
        testB->printout();
        testB->c2 = 2;
    }
    else
        std::cout << "Error casting b to testB" << std::endl;
}

you obtain the following output

childa
childa out
Error casting b to testB
Salvatore Avanzo
  • 2,656
  • 1
  • 21
  • 30