-3

Why does dynamic_cast<new>(old) change old?

Example code:

#include <iostream>
#include <string>

class MyInterface {
public:
  virtual void say() = 0;  
  virtual ~MyInterface() { }
};

class SubInterface : public MyInterface {
public:
  std::string test = "test";
  virtual void say() = 0;
  virtual ~SubInterface() { }
};

class Example : public SubInterface { 
public:
  void say() {
    std::cout << test << std::endl;
  } 
}; 


int main() {
  MyInterface* ex1 = new Example(); 
  SubInterface* ex2 = dynamic_cast<SubInterface*>(ex1);
  if (ex2 != nullptr) {
    std::cout << "call ex2->say(): ";
    ex2->test = "something else";
    ex2->say();
  }
  else { 
    std::cout << "error" << std::endl;
  }

  std::cout << "call ex1->say(): ";
  ex1->say();

  std::cerr << "debug: ex1=" << ex1 << "; ex2=" << ex2 << std::endl;

  return 0;
}

Which outputs:

call ex2->say(): something else
call ex1->say(): something else
debug: ex1=0xf1e010; ex2=0xf1e010

So I expected ex2 to be different from ex1 and therefore expected ex2->test = "something else"; not to change ex1. I guess this is intended behaviour, but why? (If they are not different, why would it even be necessary to assign anything to the result of dynamic_cast? (One could keep on using ex1?))

Any help is appreciated.

matsjoyce
  • 5,744
  • 6
  • 31
  • 38
mstrkrft
  • 53
  • 5
  • Have you seen http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used? – matsjoyce Dec 05 '14 at 16:21
  • 4
    Why would you expect them to be different? They are two pointers to the *same object*, just via *different interfaces*. – cdhowie Dec 05 '14 at 16:25
  • BTW, it's worth noting that even if the raw pointer value in `ex1` didn't equal that in `ex2`, they would still point to the same object. Down- or up-casting an object pointer can result in a different memory address, depending on how the compiler lays out the vtables for each class in the hierarchy. (This is especially true with multiple inheritance.) – cdhowie Dec 05 '14 at 16:28
  • —1: Please check your assumptions _before_ writing a question that relies on them being correct. – Lightness Races in Orbit Dec 05 '14 at 16:36

4 Answers4

5

I guess this is intended behaviour, but why?

You are casting a pointer to a different type, not creating a new object. Both point to the same Example object; one treats it as MyInterface, the other as SubInterface. So, after modifying the object through one pointer, changes to it are visible through the other, since both point to the same object.

If they are not different, why would it even be neccessary to assign anything to the result of dynamic_cast?

They are not necessarily the same. With multiple inheritance, different base-class sub-objects might be at different locations within the complete object. In that case, a down-cast might have to adjust the pointer value to point to the complete object.

One could keep on using ex1?

No. Even if, as in your case, it does have the same value, it has the wrong type. It's declared to point to MyInterface, which doesn't have a testmember, so you couldn't say ex1->test.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

ex1 and ex2 are pointing to the same object, but with different types. In other words, the memory is the same (the same Example object), but how you manipulate the memory is done through two different interfaces (MyInterface or SubInterface).

dynamic_cast is a run-time cast that can be used to safely manipulate data through a different (related) interface than another variable's type would allow. There are plenty of uses for this, though your example doesn't need it of course.

Jonny D
  • 2,244
  • 15
  • 22
1

What dynamic_cast does is just additionally verifies that the actual type of the pointed object matches the one you expect and returns nullptr if they don't. If they do match, it returns a pointer to the same object, as if you've made a static_cast (figuratively speaking, there are some other subtle differences beside the run-time check). This additional verification doesn't create new objects. dynamic_cast didn't change the object - you did.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
  • 1
    It can actually return a different pointer value, but one that points to (and hence will compare equal to) the original object. – cdhowie Dec 05 '14 at 16:32
  • @cdhowie Thanks, clarified that. – BartoszKP Dec 05 '14 at 16:33
  • 1
    Thanks. For anyone who is confused by what I mean, [here is an example](http://ideone.com/QW7U7p). Note that the `B` pointer isn't the same value as the `C` pointer, but it still compares equal to it. – cdhowie Dec 05 '14 at 16:36
1

Dynamic_cast never changes the original object, in your case 'ex1'. The memory originally allocated stays intact. Otherwise, you would have all kinds of leaks and memory corruptions.

Your intent also seems to be to understand whether it can give you a pointer different from the input one.

To understand this, you have to reason in two directions - upcasting and downcasting and inheritance and member variables etc.

There are excellent answers by others on this subject. Suggest searching for related ones.

KalyanS
  • 527
  • 3
  • 8