2017-06-28 11 views
0

「クロスキャスト」はなぜ機能しないのですか?static_castの失敗を使用している "クロスキャスト"試行。どうして?

次に、このオブジェクトの継承モデル作成:D:ここ

 FOOD 
    / \ 
CHEESE CAKE 

を私はチーズケーキを作り、cheeseからcakeへのポインタをstatic_castを試みます。私はアップルクラン/ LLVMから、次のエラー取得しています:

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

をしかし、彼らは継承によって関連している:彼らは兄弟です。私はfloatintを唱えるよう

は、なぜ私は、cakecheeseをキャストすることはできませんか?同じ基本クラスを継承した派生オブジェクトから「クロスキャスト」できないのはなぜですか?

エラーを強調するために、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; 
} 

答えて

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 
+1

しかし、相続が仮想ではないので、それは2倍のカロリーです:( – Quentin

+0

私は2つを組み合わせてチーズケーキを作りたくない、私はチーズケーキを「チーズ」の代わりに「ケーキ」オブジェクト – kmiklas

1

not related by inheritanceあなたは鋳造ポインタ(またはその逆)の値をキャスト間違えてはいけません...同じ枝に

を意味し、それらは異なるタイプです変換。

floatintは(それがその特定のケース、すなわち用暗黙であり、この機能は、明示的または暗黙的であってもよいことに注意ターゲット・タイプの値に指定された型の値を変換する関数を使用している。で定義されていますラングゲージ)。 C++では、タイプBの値を受け取ることができるクラスAのctorを実装するか、またはタイプAの値を返すクラスBのキャスト演算子を実装することによって、カスタムクラスタイプに実装できます。

Cake *Cheese *値を変換せずに、指定されたオブジェクトを別の方法で表示しようとします。それはサブタイプの多型です(dynamic_castを使用する必要があります)。あなたのタイプ階層を考えると、Cheeseオブジェクトは、CheeseオブジェクトをポイントするためにFoodポインタを使用することによって、Foodオブジェクトとして簡単に表示できます(変換されません)(別の人が違うように見えるようにまたはあなたがいつも同じ人である間は医者があなたを理解することができます!)チーズオブジェクトがどのように反応するかは、チーズをケーキとして見ることができないことは明らかです(少なくとも階層的には)ケーキの具体的な方法は?あなたは動物、犬でもありますが、私はあなたを犬のように見ることができると想像するのは難しいです(あなたは4脚ではありませんか... ...

Do notあなたの事件に騙されてしまいます。さて、チーズとケーキの内容は同じですが、与えられた階層構造が真実を伝えているようです。同じブランチにはないので、ケーキのポインタからチーズのポインタを得ることはできません。 C++コンパイラはこれに対してあなたを保護します。

チーズとケーキを継承したチーズケーキのように複数の継承を使用すると、状況が少し変わります。その後、CheeseCakeオブジェクトがCheeseポインタを介して表示されている場合、CheeseCakeが両方であるため、これをCakeポインタに変換することは可能です。もちろん、複数の継承シナリオでも、チーズオブジェクトは、ポインタを介してCakeとして見ることはできません。

+0

しかし、同じ論理がキャスト値に当てはまるのではないでしょうか?浮動小数点を整数に変換するとしましょう。今では、整数の小数点を切り捨てることはできますか?フロートからイントロへのキャストの後で、これらのどれも意味をなさない...しかし、私たちはまだそれを行います。 – kmiklas

+0

値をキャストすると、タイプを別のものに変換します型キャストでは、常に1つのオブジェクトがありますが、2つの値があります。 (ポインタはオブジェクト上のビューです)、変換はまったくありません(私はOPとしてあなたを見ることができ、あなたの友人のいくつかは、サッカー選手、同じ人、2つの異なるビュー、 、あなたとやりとりする異なる方法のみ)。 –

関連する問題