Crosscasting - why and how in the world does it work??

I'm currently reading through a C++ course and I got to a point where they give an example of using "static_cast" the wrong way, so that two pointers of a superclass type are each "static_cast"-ed to the wrong subclass object.
Objects of 2 subclasses that are descendants of the same superclass have been previously created.

My question is this: when it comes across this instruction:

 
static_cast<Dog *>(a_pet1) -> MakeSound();


how in the world does the compiler figure out that an object of type Dog* even exists?

The a_pet1 pointer is pointing to an existing object of type Cat.

What if we had multiple objects of type Dog already created. How would the compiler choose the Dog object to which a_pet1 should be cast?

This is the full code of the example?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream> 
#include <string>
using namespace std;

class Pet {
    protected:
	string Name;
    public:
	Pet(string n) { Name = n; }
	void Run(void) { cout << Name << ": I'm running" << endl; }
};

class Cat : public Pet {
    public:
	Cat(string n) : Pet(n) {};
	void MakeSound(void) { cout << Name << ": Meow! Meow!" << endl; }
};

class Dog : public Pet {
    public:
	Dog(string n) : Pet(n) {};
	void MakeSound(void) { cout << Name << ": Woof! Woof!" << endl; }
};

int main(void) {
	Pet *a_pet1 = new Cat("Tom");
	Pet *a_pet2 = new Dog("Spike");

	a_pet1 -> Run();
	static_cast<Dog *>(a_pet1) -> MakeSound();	// if we use "<Dog *>", cat will bark
	a_pet2 -> Run();
	static_cast<Cat *>(a_pet2) -> MakeSound();	// if we use "<Cat *>", dog will meow

	//	this will print:
	// Tom: I'm running
	// Tom: Woof! Woof!
	// Spike: I'm running
	// Spike: Meow! Meow!

	// static_cast<Dog *>(a_pet1) forces the compiler to assume
	// that a_pet1 is (temporarily) converted into a pointer of type Dog*

	delete a_pet2;
	delete a_pet1;
	
	return 0;
}
Last edited on
> how in the world does the compiler figure out that an object of type Dog* even exists?

It does not. The correctness of all casts except dynamic_cast is the responsibility of the programmer.


> The a_pet1 pointer is pointing to an existing object of type Cat.
> How would the compiler choose the Dog object to which a_pet1 should be cast?

The compiler would assume that the a_pet1 pointer is pointing to the Pet sub-object of a complete object of type Dog. Since it does not, the program has undefined behaviour.
Last edited on
OK, I see, so the answer here is that the compiler will have undefined behaviour in this case.

I was baffled by the fact that I personally compiled this with g++-4.9 in Linux, and I ran it and yes, the cat barks and the dog meows!! There is no compilation error and no runtime error.

But I'm supposed to understand that some different compiler might behave differently if given this challenge...

OK, thank you for answering!
> some different compiler might behave differently if given this

The same compiler - or for that matter, the same compiled program - might behave differently the next time. With undefined behaviour, all bets are off.

As an aside, update your compiler: g++-4.9 does not have a conforming standard library. Move to at least 5.1.
Topic archived. No new replies allowed.