抽象クラスにアップキャストし、そこからクラスが派生するたびに変更しない方法はありますか?
-
26-09-2019 - |
質問
#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
ウィルの仕事ます。
あなたはちょうどあなたがbb
前B*
が本当にstatic_cast
であることをする必要があります。
またdynamic_cast
が正しい型でない場合はnullポインタを返しますbb
を使用することができます。
他のヒント
これは、継承と抽象インタフェースの目的を破っています。 bye
とsayonara
は異なる言語で、同じこと(言って別れを)やるの両方。この手段あなたはサブクラスでオーバーライドされます抽象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
あなたが本当にそれを必要とする場合にのみ、これを行います。