抽象クラスにアップキャストし、そこからクラスが派生するたびに変更しない方法はありますか?

StackOverflow https://stackoverflow.com/questions/3829220

質問

#include<iostream>
using namespace std;

class Abs
{
        public:
        virtual void hi()=0;
};

class B:public Abs
{
        public:
        void hi() {cout<<"B Hi"<<endl;}
        void bye() {cout<<"B Bye"<<endl;}
};
class C:public Abs
{
        public:
        void hi() {cout<<"C Hi"<<endl;}
        void sayonara() {cout<<"C Sayonara"<<endl;}
};

int main()
{
        Abs *bb=new B;
        bb->bye();
        Abs *cc=new C;
        cc->sayonara();
}//main

コンパイラは言う

test2.cpp: In function ‘int main()’:
test2.cpp:26: error: ‘class Abs’ has no member named ‘bye’
test2.cpp:28: error: ‘class Abs’ has no member named ‘sayonara’

この問題のため、Abs クラスを継承する新しい派生クラスを作成するたびに、Abs クラスに関数を追加する必要があります (アップキャストは必須です)。私が計画しているプログラムではそうする必要があります)。一度作成した基本クラスには触れたくありません。この問題は、一度基本クラスを作成したら、それを変更する必要はないという原則に違反していませんか。この問題を解決する方法はありますか?追伸:工場設計パターンと試作設計パターンを見てきましたが、どちらも解決できないようです。

役に立ちましたか?

解決

さて、私はあなたが欲しい(とあなたがそのようにする理由)正確に理解してないんだけどます:

int main()
{
        Abs *bb=new B;
        static_cast<B*>(bb)->bye();
        Abs *cc=new C;
        static_cast<C*>(cc)->sayonara();
}//main

ウィルの仕事ます。

あなたはちょうどあなたがbbB*が本当にstatic_castであることをする必要があります。

またdynamic_castが正しい型でない場合はnullポインタを返しますbbを使用することができます。

他のヒント

これは、継承と抽象インタフェースの目的を破っています。 byesayonaraは異なる言語で、同じこと(言って別れを)やるの両方。この手段あなたはサブクラスでオーバーライドされます抽象say_goodbyeメソッドを持つ必要があります。私たちは、より具体的な支援を提供できるようので、多分あなたは、実際のシナリオを記述することができ、これは簡単な例であると仮定します。

編集あなたが抽象インタフェースを介して、派生クラスのコピーを作成したい場合は、チェックアウト<のhref = "https://stackoverflow.com/questions/3063534/can-i-この質問する>」を作成・オブ・子・コピーを-ツー・スーパー・ポインタを渡したが、。あなたのサブクラスの異なる属性を明示的にアクセスする場合でも、ESをサブクラス化する場合、あなたはあなたの自己を問うべきであるあなたのクラスは多くの共通点を持っているように思わないので、ここでは適切ます。

int main()
{
        B *bb = new B;
        bb->bye();
        C *cc=new C;
        cc->sayonara();
}//main

基底クラスでこの方法の変形はもはや必要とされない。)

ダイナミックキャストは賢明な選択肢です。

:あなたが動的キャストについての宗教している場合は、ビジターデザインパターンを使用することができます
struct Abs;
struct B;
struct C;

struct Visitor
{
    virtual ~Visitor() {}

    // Provide sensible default actions
    virtual void visit(Abs&) const { throw "not implemented"; }
    virtual void visit(B& b) const { visit(static_cast<Abs&>(b)); }
    virtual void visit(C& c) const { visit(static_cast<Abs&>(c)); }
};

struct Abs
{
    virtual ~Abs() {}
    virtual void hi() = 0;
    virtual void accept(Visitor const& v) { v.visit(*this); }
};

struct B : Abs
{
    void hi() { ... }
    void accept(Visitor const& v) { v.visit(*this); }
    void bye() { ... }
};

struct C : Abs
{
    void hi() { ... }
    void accept(Visitor const& v) { v.visit(*this); }
    void sayonara() { ... }
};

struct DoSayonara : Visitor
{
    void visit(C& c) const { c.sayonara(); }
};

struct DoBye : Visitor
{
    void visit(B& b) const { b.bye(); }
};

struct ByeOrSayonara : Visitor
{
    void visit(B& b) const { b.bye(); }
    void visit(C& c) const { c.sayonara(); }
};

と、あなたが使用して

Abs* b = new B(); Abs* c = new C();
b->accept(DoSayonara()); // Throw an exception
c->accept(DoSayonara()); // Do what is expected

あなたが本当にそれを必要とする場合にのみ、これを行います。

アップキャストが必須で、サブクラスで定義されたメソッドを呼び出す必要がある場合、それは間違っています。

ただし、特定の時点では、オブジェクトが特定のサブクラスであることがわかっている場合 (その場合、その型に動的にキャストできる)、またはわかっておらず、関数を呼び出すことができるかどうかのどちらかです。

これがあなたの問題に関連していると仮定すると、 その他の質問, 、その特定の問題を別の方法で実装する方法を説明しようとしました そこには.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top