C ++中的向上转换和向下转换

时间:2018-04-26 02:06:29

标签: c++ dynamic-cast downcast upcasting

我正在尝试使用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

`

2 个答案:

答案 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的代码而只是分配它,因此它成功了。