2017-12-01 21 views
0

私は、悪いクラス階層のこのようなひどい問題にちょっと悩まされています。実際の基本クラスにアップキャストする

class A {...}; // abstract 
class B : public A {...}; // abstract 
class C {...}; // abstract 

class a1 : public B, public C {...}; // indirect inheritance of A 
class c1 : public A, public C {...}; 

質問:それはクラスAへのポインタ(参照)にCへのポインタ(参照)を変換可能である

私は最善の解決策は、Cは、Aから継承しただけでクラスを作ることであることを理解しますが、それでもクラスa1(2つの基底A)に何らかの問題を引き起こす可能性があります。

+0

CとAはありませんので、あなたは、静的なキャストと2の間で変換することができない、完全に無関係です。あなたはそれらの変換演算子を作成することができるかもしれません(または再設計することができます) – UKMonkey

答えて

3

質問:それは可能であるクラスAへのポインタ(参照)にCへのポインタ(参照)を変換

ていないクラスは、多型でない限り、即ち、少なくとも1つの仮想メンバ関数を有します。その場合、StoryTellerの答えに示すように、dynamic_castをサイドキャストに使用することができます。

Cポインタ(参照)がAを継承する子を指している場合は、最初にその子ポインタにキャストしてからAにキャストすることができます。あなたはその具体的な種類は不明であるだけで、任意のCポインタを変換することはできませんので、必ずもちろん理想的ではないのです

c1 c; 
C& cref = c; 
A& aref = static_cast<c1&>(cref); 

私は最善の解決策は、ちょうどクラスCは、あなたがこれをしなかった場合、すべてのCポインタがAポインタに暗黙的に変換だろう

から継承させることであることを理解しています。

しかし、それでもクラスa1(2つのベースA)にはいくつかの問題が発生する可能性があります。

問題を回避するには、共有ベース、つまり仮想継承が必要です。

struct A {}; // abstract 
struct B : virtual A {}; // abstract 
struct C : virtual A {}; // abstract 

struct a1 : B, C {}; // indirect inheritance of A 
struct c1 : C {}; 

int main() { 
    c1 c; 
    C& cref = c; 
    A& aref = cref; 
} 
3

あなたがしようとしていることを「サイドキャスト」といいます。そして、組み込みのdynamic_cast式でそれを行うことができます。しかし、それは安くはないので、あなたのプロジェクトでRTTIのサポートを無効にした方が良いでしょう(あなたはクラスが抽象であると言いましたので、RTTIを生成するために宣言が必要な仮想関数が必要です)。

を再設計し、あなたのクラスは私の意見では、高度に保証されてする必要が約Live

#include <cassert> 

struct A { 
    virtual ~A() = default; 
}; 

struct B : public A { 
    virtual ~B() = default; 
}; 

struct C { 
    virtual ~C() = default; 
}; 

struct a1 : public B, public C { 
    a1() = default; 
    virtual ~a1() = default; 

}; // indirect inheritance of A 

int main() { 
    a1 a; 

    C* c = &a; 

    assert(dynamic_cast<A*>(c) != nullptr); 

    return 0; 
} 

しかし、あなたの感情、それを参照してください。サイドキャストをする必要はありません。

+0

dynamic_castを許可するには、仮想メンバー関数の追加が必要であることを明示的に言及します。 – user2079303

+0

@ user2079303 - ありがとう、仮定を明示しました。私はそのクラスが抽象であると言って、OPの外に出ていました。 – StoryTeller

0

上記の両方の答えは正しいですが、最初の方がより広く説明されていると思います。私はおそらくのような、奇妙な訪問者を作成して使用します 別の解決策:

PointerCreator 
{ 
    void visit (const a1 & _a) 
    { 
    m_pointerToA = &_a; 
    } 

    void visit (const c1 & _c) 
    { 
    m_pointerToA = &_a; 
    } 

    A * m_pointerToA; 
}; 

PointerCreator pC; 
a1.accept(pC); 
A& = *pC.m_pointerToA; 
+0

まあ、たぶんいつか役に立つかもしれません...しかし、私はそれを行う通常の方法とは考えません。訪問者を使用する場合、訪問者が特定のアクションを実行することを好むかもしれません。適切な場合、ターゲットがない場合や複数のターゲットを処理できるようになります... – Phil1970

関連する問題