我正在尝试使用Visual Studio C ++ 2010 Express在C ++中进行强制转换以及使用dynamic_cast。 但不知何故,当我运行它时,猫对象实际上可以执行狗行为。
似乎狗 d =(狗)aa; 让编译器感到困惑。有什么建议吗?
以下是我的代码。
`
#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;
}
输出
构建动物Catty
构建Cat
凯蒂
hello woof ....有效演员
hello woof .... Catty
`
答案 0 :(得分:2)
Dog *d = (Dog*)aa;
类型转换的括号样式称为C-style cast,因为它被设计为模仿C的行为。在这种情况下,编译器执行static_cast
,进入向下转换{{1在假设上{}为Animal*
,基础对象为Dog*
。因为底层对象实际上是Dog
,所以程序格式不正确,任何事情都可能发生,包括内存损坏。 C风格的演员阵容从不进行任何运行时安全检查。
Cat
此演员实际上不需要做任何事情:它正在从Dog* dog = dynamic_cast<Dog*>(d);
转换为Dog*
。即使使用Dog*
,也不必进行运行时安全检查,因为dynamic_cast
被假定为格式良好的d
。
避免使用C风格的演员表。确保任何向下转发有效。我个人不会非常使用Dog*
,但是我的责任在于我只能适当地贬低。
答案 1 :(得分:1)
Animal *aa = new Cat("Catty"); // cat upcasting to animal
Dog *d = (Dog*)aa; // animal downcasting to dog. ???
这是未定义的行为,您将需要一些关于v-tables的低级实现的知识,以了解调用导致woof的原因。在那之前,要知道应该避免未定义的行为。
Dog* dog = dynamic_cast<Dog*>(d);
由于d已经是Dog *,编译器可能不会生成执行RTTI的代码而只是分配它,因此它成功了。