"跨铸造"尝试使用static_cast失败;为什么?

时间:2017-06-28 18:39:15

标签: oop c++11 polymorphism dynamic-cast static-cast

为什么没有"交叉演员"工作?

以下创建此对象继承模型:

     FOOD
    /    \
 CHEESE  CAKE

在这里,我尝试static_castcheesecake的指针,制作芝士蛋糕:D。我从Apple Clang / LLVM收到以下错误:

 ERROR: Static cast from 'Cheese *' to 'Cake *', which are not related by inheritance, is not allowed

但他们与继承有关:他们是兄弟姐妹。

为什么我无法将cheese投射到cake,就像我将int投放到float一样?为什么我不能"交叉演员"来自继承自相同基类的派生对象?

包含static_castdynamic_cast次尝试的最小,完整且可验证的示例,以突出显示错误。

#include <iostream>
#include <string>

class Food {
public:
    Food(std::string brand):brand_(brand) {}
    virtual ~Food() {};
    std::string brand() { return brand_; }
    virtual void cut()const { std::cout << "Food cut." << std::endl; }
    void eat()const { std::cout << "Food eaten." << std::endl; }
private:
    std::string brand_;
};

class Cheese : public Food {
public:
    Cheese(std::string brand):Food(brand) {};
    virtual void cut()const { std::cout << "Cheese cut.\n"; }
    void eat()const { std::cout << "Cheese eaten.\n"; }
};

class Cake : public Food {
public:
    Cake(std::string brand):Food(brand) {};
    virtual void cut()const { std::cout << "Cake cut.\n"; }
    void eat()const { std::cout << "Cake eaten.\n"; }
};

int main() {
    Food f("tbd");
    Cheese c("Cheddar");
    Cake cc("Cheesecake");
    Food * food_ptr;
    Cheese *cheese_ptr, *cheeseCake_ptr;
    Cake *cake_ptr;

    food_ptr = &f;
    food_ptr->cut();  //-> "Food cut."

    food_ptr = &c;
    food_ptr->cut();  //-> "Cheese cut." Result of virtual keyword.

    cheese_ptr = dynamic_cast<Cheese*> (food_ptr);
    cheese_ptr->cut(); //-> "Cheese Cut." The downcast worked

    food_ptr = &cc;
    cake_ptr = dynamic_cast<Cake*> (food_ptr);
    cake_ptr->cut(); //-> "Cake Cut." pointer reassignment and downcast worked.


    cheeseCake_ptr = dynamic_cast<Cheese*> (food_ptr);
    cheeseCake_ptr->cut(); //-> "Cake cut." Again, Food* dynamically casted to Cheese*

    /* ~~~ NOTE: THE FOLLOWING EXAMLES INTENTIONALLY THROW ERRORS ~~~ */

    /*
     Dynamic cross-cast attempt:
     ERROR: Assigning to 'Cheese *' from incompatable type 'Cake *'
     Dynamic cast: doensn't make sense, as the relationshiop between cheese and cake is not polymorphic
    */

    cheeseCake_ptr = dynamic_cast<Cake*> (cheese_ptr);
    cheeseCake_ptr->cut();

    /*
     Static cross-cast attempt:
     ERROR: Static cast from 'Cheese *' to 'Cake *', which are not related by inheritance, is not allowed
     Static cast: why doesn't this work? We know the data types.
     */

    cheese_ptr = &c;
    cake_ptr = &cc;
    cheeseCake_ptr = static_cast<Cake*> (cheese_ptr);

    std::cout << "\n\n";
    return 0;
}

2 个答案:

答案 0 :(得分:1)

not related by inheritance意味着在同一个分支上......

你不应该将转换值误认为是转换指针(或反过来),它们是不同的类型转换。

intfloat 使用函数将给定类型的值转换为目标类型的值(请注意,此函数可以是显式或隐式,它隐含于该特定情况,即在语言中定义的)。在C ++中,您可以在自定义类类型上实现此功能,方法是为类A实现能够接收类型B值的ctor,或者通过为类B实现返回类型A值的强制转换操作符。

Cake *Cheese * 不会转换值,但会尝试以不同的方式查看给定对象。它是子类型多态(因此您需要使用dynamic_cast)。给定您的类型层次结构,通过使用Food指针指向Cheese对象,可以轻松地将Cheese对象视为(不转换)为Food对象(就像您可以被不同的人看到的那样,(想想朋友,教授的方式)或者当你总是同一个人时,医生可以逮捕你!)。很明显(至少在你的等级中)奶酪不能被视为蛋糕,如果奶酪对象会如何对蛋糕的具体方法做出反应?你也是一只动物,也是一只狗,但我很难想象我会把你视为一只狗(你不会有4条腿不是吗? ...

不要被你的案子所欺骗。好吧,看起来Cheese和Cake的内容是相同的,但是给定的层次结构说实话:在同一个分支上没有,你不能从Cake指针获得一个Cheese指针。 C ++编译器可以防止这种情况发生。

如果你使用继承自Cheese和Cake的CheeseCake之类的多重继承,现在情况会略有改变。然后给定通过Cheese指针查看的CheeseCake对象,可以将它转换为Cake指针,因为CheeseCake都是!当然,即使在多重继承场景中,也不能通过指针将Cheese对象视为Cake。

答案 1 :(得分:0)

错误说明了一切,ERROR: Static cast from 'Cheese *' to 'Cake *', which are not related by inheritance, is not allowed。尽管他们是兄弟姐妹,但他们并没有通过继承来解决。

如果你想制作芝士蛋糕,你可以做多重继承。

    FOOD
   /    \
CHEESE   CAKE
   \     /
  CHEESECAKE

像这样:

class CheeseCake : public Cake, public Cheese