3
#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 クラスに関数を追加する必要があります (アップキャストは必須です。私が計画しているプログラムでは、そうする必要があります)。一度作成された基本クラスには触れたくありません。この問題は、基本クラスを作成すると、それを変更する必要がないという原則に違反していませんか。この問題を解決する方法はありますか? ps: 工場設計パターンとプロトタイプ設計パターンを見てきましたが、どちらも解決できないようです。

4

5 に答える 5

4

これは、継承と抽象インターフェイスの目的を無効にしています。どちらも同じこと (別れを告げる) を行いますが、言語が異なるだけですbye。これは、サブクラスに対してオーバーライドされるsayonara抽象メソッドが必要であることを意味します。say_goodbyeこれは単純化された例だと思いますので、実際のシナリオを説明していただければ、より具体的なヘルプを提供できます。

編集抽象インターフェイスを介して派生クラスのコピーを作成する場合は、この質問を確認してください。サブクラスのさまざまな属性に明示的にアクセスしたい場合は、クラスに共通点があまりないように見えるため、ここでサブクラス化が適切かどうかを自問する必要があります。

于 2010-09-30T09:19:55.633 に答える
3

まあ、私はあなたが何を望んでいるのか(そしてなぜあなたがそれを望んでいるのか)を正確に理解することはできませんが、

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

動作します。

bbそれが本当にあなたのB*前にあることを確認する必要がありますstatic_cast

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

于 2010-09-30T09:14:23.470 に答える
2
int main()
{
        B *bb = new B;
        bb->bye();
        C *cc=new C;
        cc->sayonara();
}//main

このようにして、基本クラスの変更は不要になります:)

于 2010-09-30T09:24:51.040 に答える
1

動的キャストは賢明なオプションです。動的キャストに熱心な場合は、ビジター デザイン パターンを使用できます。

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

これは、本当に必要な場合にのみ行ってください。

于 2010-09-30T09:27:59.647 に答える
0

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

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

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

于 2010-09-30T09:44:30.730 に答える