デコレータパターンがどのように機能し、どのくらい私が「ストレッチ」できるかを理解しようとしています。 thisの例に続いて、私はクラスXYZを拡張しました。派生クラス "KLM"(XYZから)デコレータのインスタンス化にC++のdynamic_castが失敗する
具体的には、私はデコレータパターンを持っていますが、派生デコレータクラス "KLM"は基本クラス "XYZ"のいずれにも表示されないいくつかの機能を持っています。 「D」、「I」または「A」。通常、私は
I * inKLM = new L(new M(new K(new A)));
などのオブジェクトをインスタンス化だろうがこれは私がK::doVirtR()
、L :: doVirtS()とM :: doVirtT()関数にアクセスすることを許可しないように
(以下のコードを参照してください)。これらにアクセスするには、クラス "KLM"のそれぞれにdynamic_cast
を使用してinKLMポインタをダウンキャストする必要があります。
問題は、上記の式の左端new
に対してのみこれを行うことができます。ダイナミックキャストのために多態性を維持する必要があることを読んだので、すべての関数で仮想デストラクタを使用しようとしました。それでも、 "外側の" new
操作(この場合はクラス "L"のオブジェクト)以外のもので動作するように動的キャストを取得することはできません。
このコードをご覧ください。 dynamic_castingで "LinKLM"だけでなく、 "MinKLM"と "KinKLM"を成功させるにはどうすればいいですか?
#include <iostream>
#include <list>
using namespace std;
class D; //decorator base
struct I { //interface (for both Base and DecoratorBase
I(){
cout << "\n| I::ctor ";
}
virtual ~I(){
cout << "I::dtor |" ;
}
virtual void do_it() = 0;
virtual void regDecorator(D* decorator) = 0;
virtual void train() = 0;
virtual void et() = 0;
};
class D: public I { //DecoratorBase : has same-named fns as Base (must be exported on I) and calls upon them.
public:
D(I * inner) : m_wrappee(inner) {
cout << "D::ctor ";
regDecorator(this);
}
virtual ~D() {
cout << "D::dtor ";
delete m_wrappee;
}
void do_it() {
m_wrappee->do_it();
}
virtual void et() {
cout << "filling in for lack of et() in derived class\n";
} //almost pure virtual, just not implemented in all derived classes
void train(){
m_wrappee->train();
}
private:
void regDecorator(D* decorator){
m_wrappee->regDecorator(decorator);
}
I * m_wrappee;
};
class A: public I { //Base has all the basic functionality
public:
A() {
cout << "A::ctor " ;
decList.clear();
}
~A() {
cout << "A::dtor |" ;
}
void do_it() {
cout << 'A';
}
void train(){
et();
}
void regDecorator(D* decorator)
{
if (decorator) {
cout << "reg=" << decorator << " ";
decList.push_back(decorator);
}
else
cout << "dec is null!" <<endl;
}
private:
void et()
{
//size_t counter=0;
list<D*>::iterator it;
for(it=decList.begin(); it != decList.end(); it++)
{
//if ((*it)->et())
(*it)->et();
//else
// cout << "couldnt et cnt=" << counter << endl;
//counter++;
}
}
std::list<D*> decList;
};
class X: public D { //DerivedDecoratorX ..
public:
X(I *core): D(core){
cout << "X::ctor ";
}
virtual ~X() {
cout << "X::dtor ";
}
void do_it() {
D::do_it();
cout << 'X';
}
void doX() {
cout << "doX" << endl;
}
protected:
virtual void doVirtR() = 0;
private:
void et(){
cout << "X::et" <<endl;
}
};
class K: public X {
public:
K(I * core):X(core) {
cout << "K::ctor " ;
}
virtual ~K() {
cout << "K::dtor ";
}
void doVirtR(){
cout << "doVirtK" <<endl;
}
};
class Y: public D {
public:
Y(I *core): D(core){
cout << "Y::ctor ";
}
virtual ~Y() {
cout << "Y::dtor ";
}
/*void et(){
cout << "Y::et" <<endl;
}*/
void do_it() {
D::do_it();
cout << 'Y';
}
void doY() {
cout << "doY" << endl;
}
protected:
virtual void doVirtS() = 0;
};
class L: public Y{
public:
L(I * core):Y(core) {
cout << "L::ctor ";
}
virtual ~L() {
cout << "L::dtor ";
}
void doVirtS(){
cout << "doVirtL" <<endl;
}
};
class Z: public D {
public:
Z(I *core): D(core){
cout << "Z::ctor ";
}
virtual ~Z() {
cout << "Z::dtor ";
}
void et(){
cout << "Z::et" <<endl;
}
void do_it() {
D::do_it();
cout << 'Z';
}
void doZ() {
cout << "doZ" << endl;
}
virtual void doVirtT() = 0;
};
class M: public Z{
public:
M(I * core):Z(core) { //must add D(core) here explicitly because of virtual inheritance in M's base class (Z).
cout << "M::ctor " ;
}
virtual ~M() {
cout << "M::dtor ";
}
void doVirtT(){
cout << "doVirtM" <<endl;
}
};
int main(void) //testing dynamic casting
{
I * inKLM = new L(new M(new K(new A)));
L * LinKLM = dynamic_cast<L *>(inKLM);
M * MinKLM = dynamic_cast<M *>(inKLM);
K * KinKLM = dynamic_cast<K *>(inKLM);
cout << endl;
if (! MinKLM) cout << "null MinKLM!" << endl;
if (! LinKLM) cout << "null LinKLM!" << endl;
if (! KinKLM) cout << "null KinKLM!" << endl;
//KinKLM->doVirtR();
//LinKLM->doVirtS();
//MinKLM->doVirtT();
//LinKLM->D::train();
//KinKLM->do_it();
//MinKLM->doZ();
delete inKLM;
cout << endl;
return 0;
}
なぜあなたのコンストラクタはptrsをベースクラスにするのですか?たとえば、あなたのサンプルから 'I * inKLM = new L(new M(new K)));'が可能な限りリークするようです。 –
@BenjaminBannier私が理解しているように、これはデコレータパターンの中心です。 – nass