mercredi 28 juin 2017

"Cross-cast" attempt using static_cast failing; why?

Why doesn't ths "cross-cast" work?

The following creates this object inheritance model:

     FOOD
    /    \
 CHEESE  CAKE

Here I attempt to static_cast a pointer from cheese to cake, making a cheesecake :D. I am getting the following error from Apple Clang/LLVM:

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

But they ARE related by inheritance: they are siblings.

Why can't I cast a cheese to a cake, like I cast an int to a float? Why can't I "cross-cast" from derived objects which inherit from the same base class?

Complete, verifiable example follows, with static_cast and dynamic_cast attempts included, to highlight errors.

#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;
}

Aucun commentaire:

Enregistrer un commentaire