【发布时间】:2012-04-14 07:48:16
【问题描述】:
首先,我知道我做不到,我认为这不是重复的问题(this 和 this 问题处理相同的问题,但他们只想解释为什么它不起作用) .
所以,我对类和继承有类似的概念,并且我会以某种方式优雅地想做一些被禁止的事情。这是一个非常简单的代码 sn-p,它反映了我想要做的事情:
#include <iostream>
class A{
protected:
int var;
std::vector <double> heavyVar;
public:
A() {var=1;}
virtual ~A() {}
virtual void func() {
std::cout << "Default behavior" << this->var << std::endl;
}
// somewhere along the way, heavyVar is filled with a lot of stuff
};
class B: public A{
protected:
A* myA;
public:
B(A &a) : A() {
this->myA = &a;
this->var = this->myA->var;
// copy some simple data, e.g. flags
// but don't copy a heavy vector variable
}
virtual ~B() {}
virtual void func() {
this->myA->func();
std::cout << "This class is a decorator interface only" << std::endl;
}
};
class C: public B{
private:
int lotsOfCalc(const std::vector <double> &hv){
// do some calculations with the vector contents
}
public:
C(A &a) : B(a) {
// the actual decorator
}
virtual ~C() {}
virtual void func() {
B::func(); // base functionality
int heavyCalc = lotsOfCalc(this->myA->heavyVar); // illegal
// here, I actually access a heavy object (not int), and thus
// would not like to copy it
std::cout << "Expanded functionality " << heavyCalc << std::endl;
}
};
int main(void){
A a;
B b(a);
C c(a);
a.func();
b.func();
c.func();
return 0;
}
这样做的原因是我实际上是在尝试实现一个Decorator Pattern(class B 有我想要装饰的myA 内部变量),但我也想使用一些受保护的class A 的成员在进行“装饰”计算时(在 class B 及其所有子类中)。因此,这个例子不是一个合适的装饰器例子(甚至不是一个简单的例子)。在示例中,我只专注于演示有问题的功能(我想使用但我不能使用的功能)。在这个示例中,甚至没有使用实现装饰器模式所需的所有类/接口(我没有 抽象基类接口,由具体基类实例继承以及一个抽象装饰器接口,用作具体装饰器的超类)。我只提到上下文的装饰器(我想要一个A* 指针的原因)。
在这种特殊情况下,我认为将 int var 公开(甚至编写可公开访问的 getter)(我的等价物)没有多大意义,原因有两个:
- 更明显的是,我不希望用户直接使用这些信息(我有一些函数可以返回与我的
protected变量相关和/或写入的信息,但是不是变量值本身) - 在我的例子中,
protected变量比int复制要重得多(它是doubles 的二维std::vector),并且将其复制到派生类的实例中是不必要的耗时耗内存
现在,我有两种不同的方法可以让我的代码做我想做的事,但我都不喜欢这两种方法,我正在寻找一个实际上打算做的 C++ 概念类似的东西(我不可能是第一个渴望这种行为的人)。
到目前为止我有什么以及为什么我不喜欢它:
1.将所有(相关)继承类friends 声明为基类:
class A{
....
friend class B;
friend class C;
};
我不喜欢这个解决方案,因为它会迫使我在每次编写新的子类时修改我的基类,而这正是我想要的我试图避免。 (我只想在系统的主要模块中使用'A'接口。)
2。将A* 指针转换为继承类的指针并使用它
void B::func(){
B *uglyHack = static_cast<B*>(myA);
std::cout << uglyHack->var + 1 << std::endl;
}
变量名非常暗示我使用这种方法的感觉,但这是我现在使用的。由于我设计了这个类,我知道如何小心并只使用在class A 中实际实现的东西,同时将其视为class B。但是,如果其他人继续我的项目的工作,他可能对代码不太熟悉。此外,将变量指针转换为我非常清楚不是的东西对我来说只是纯粹的邪恶。
我正在努力使这个项目的代码尽可能保持美观和简洁,所以如果有人对不需要不时修改基类或使用邪恶概念的解决方案有任何建议,我非常感谢。
【问题讨论】:
-
我相信在装饰器模式中,装饰器和实际对象实现一个接口,即装饰器不扩展实际实现的对象,只提供相同的接口,装饰只应用于公共接口。
-
@DavidRodríguez-dribeas 认为我在您输入评论时编辑了解释 :) 您说的是真的,但在我的实际情况下,最上面的界面包含一些常见的数据 每个类的具体实例。因此,从理论上讲,我不想访问属于任何具体实现的任何对象,只是访问在接口中实现的类的每个实例共有的一些对象。但是正如我刚刚在Q中编辑的那样,示例代码并不专注于实现示例装饰器,只是我的问题情况的一个示例。
-
我很难理解你想要做什么。我知道你想举一个简单的例子,但现在我不知道代码中哪些奇怪的东西很重要,哪些不重要。例如,在 B 的构造函数中,您复制 var 成员,但在 C 类中,您直接使用 myA->var。为什么需要副本,而您不能使用副本进行计算?让我们从那里开始,也许它会变得更清晰。
-
@lucas1024 问题是,原始示例仅显示了我想要访问的内容、位置和方式,但与装饰器模式不太相似(它只包含与真正的装饰器实现相同的对象) .实际上,我在基类中有超过 1 或 2 个 var,简单的(例如标志)我不介意复制,但重的(例如向量 - 只是添加)我 don' t 想要复制。当您留下评论时,我在示例中只使用了 1 个变量,但是我确实在我的代码中添加了我真正想访问的内容的解释。
标签: c++ design-patterns inheritance