I was trying the idea of casting in C++ using Visual Studio C++ 2010 Express and the use of dynamic_cast. But somehow, when I run it, an cat object can actually perform dog behaviour.
Seem like Dog d = (Dog )aa; got the compiler confused. Any advice?
Below is my code.
`
#include <iostream>
#include <string>
using namespace std;
class Animal {
public:
string name ;
Animal(string n) : name(n) {cout << "construct animal " << name << endl ; }
Animal() : name("none") { };
virtual string getName() { return name ; }
virtual ~Animal() { cout << "destruct animal " << name << endl ; }
};
class Dog: public Animal{
public:
Dog() :Animal("") { }
Dog(string n): Animal(n) {
cout << "construct Dog" << endl ;
}
void dogStuff() { cout << "hello woof...."; }
};
class Cat: public Animal{
public:
Cat() :Animal("") { }
Cat(string n): Animal(n) {
cout << "construct Cat" << endl ;
}
void catStuff() { cout << "hello meow...."; }
};
int main() {
Animal *aa = new Cat("Catty"); // cat upcasting to animal
Dog *d = (Dog*)aa; // animal downcasting to dog. ???
cout << d->getName() << endl;
d->dogStuff();
Dog* dog = dynamic_cast<Dog*>(d) ;
if(dog) {
cout << "valid cast" << endl ;
dog->dogStuff();
cout << dog->getName();
}else
cout << "invalid cast" << endl ;
int i ;
cin >> i ;
return 0;
}
output
construct animal Catty
construct Cat
Catty
hello woof....valid cast
hello woof....Catty
`
Dog *d = (Dog*)aa;
The parentheses style of type cast is called a C-style cast , because it is designed to mimic the behavior of C. In this case, the compiler performs a static_cast
, which proceeds to downcast Animal*
to Dog*
, on the assumption that the underlying object is Dog
. Because the underlying object is actually Cat
, the program is ill-formed, and anything can happen, including memory corruption. C-style casts never do any run-time safety checks.
Dog* dog = dynamic_cast<Dog*>(d);
This cast doesn't actually have to do anything: It's converting from Dog*
to Dog*
. A run-time safety check does not have to be done, even though dynamic_cast
is used, because d
is assumed to be a well-formed Dog*
.
Avoid the C-style casts. Make sure that any downcasts are valid. I personally don't use dynamic_cast
very much, but then the responsibility is on me to only downcast properly.
Animal *aa = new Cat("Catty"); // cat upcasting to animal
Dog *d = (Dog*)aa; // animal downcasting to dog. ???
This is undefined behaviour, you will need some knowledge on the low level implementation with v-tables to understand why the call results in a woof. Until then, know that undefined behaviour should be avoided.
Dog* dog = dynamic_cast<Dog*>(d);
Since d is already a Dog*, the compiler is probably not generating code to do RTTI and simply assigning it, hence it succeeded.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.