gpt4 book ai didi

c++ dynamic_cast 装饰器实例化失败

转载 作者:行者123 更新时间:2023-11-28 05:31:50 30 4
gpt4 key购买 nike

我想了解装饰器模式是如何工作的,以及我可以在多大程度上“扩展”它以满足我的需要。正在关注this例如,我有扩展类 XYZ。存在派生类“KLM”(来自 XYZ)

具体来说,即使我有一个装饰器模式,派生的装饰器类“KLM”有一些功能在它们的任何基类“XYZ”、“D”、“I”或“A”中都没有出现。

所以虽然通常我会将一个对象实例化为

I * inKLM = new L( new M( new K( new A )));

这将不允许我访问 K::doVirtR() 、 L::doVirtS() 和 M::doVirtT() 函数(参见下面的代码)。要访问这些,我需要使用 dynamic_cast 将 inKLM 指针向下转换为每个类“KLM”。

问题是我只设法对上面表达式中最左边的 new 执行此操作。我读到需要维护多态性才能使动态转换工作,所以我尝试在所有函数中都有一个虚拟析构函数。除了“外部”new 操作(在本例中为“L”类的对象)之外,我仍然无法让动态转换工作。

请看这段代码。我怎样才能不仅使“LinKLM”,而且使“MinKLM”和“KinKLM”在 dynamic_casting 中取得成功?

#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;
}

最佳答案

如果您需要访问某些内部类中独有的功能,您最好(取决于特定问题)尝试混合类。基本思想是让一个模板类继承它的模板参数。我简化了下面的类,但原理很清楚:

#include <iostream>

// your base class
class I {
public:
virtual void do_it() {}
};

// a decorator
template <class Base>
class T1 : public Base {

public:
void do_it() {
std::cout << "T1" << std::endl;
Base::do_it();
}

void unique_in_T1() {
std::cout << "Unique in T1" << std::endl;
}
};

// another decorator
template <class Base>
class T2 : public Base {

public:
void do_it() {
std::cout << "T2" << std::endl;
Base::do_it();
}

void unique_in_T2() {
std::cout << "Unique in T2" << std::endl;
}
};

// yet another decorator
template <class Base>
class T3 : public Base {

public:
void do_it() {
std::cout << "T3" << std::endl;
Base::do_it();
}

void unique_in_T3() {
std::cout << "Unique in T3" << std::endl;
}
};

int main(int argc, const char * argv[]) {
T3<T2<T1<I>>> my_object1;
my_object1.do_it();
my_object1.unique_in_T2();

T1<T3<I>> my_object2;
my_object2.do_it();
my_object2.unique_in_T3();
return 0;
}

您的类 D 不再需要了。该类的主要目的是包装实际完成工作的对象,同时维护I 的接口(interface)。对于 mixin 类,不再有包装,因为它已被继承取代,因此不需要 D 类。

Here是阅读更多内容的链接。

关于c++ dynamic_cast 装饰器实例化失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39312070/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com