变形还是封装,这就是问题! (C++)
我需要将多态对象(假设Polygon
)存储在另一个对象(假设Simulation
)内。同时我想保留Simulation
的封装。
class Polygon {
public:
virtual double area() { return 0; }
};
class Square : public Polygon {
public:
Square(double edge) : edge_(edge) {}
virtual double area() { return edge_*edge_; }
private:
double edge_;
};
class Simulation {
public:
Simulation(Polygon& polygon) { polygon_ = &polygon; }
Polygon* polygon() { return polygon_; }
private:
Polygon* polygon_;
};
int main (int argc, const char * argv[]) {
Square square(2.0);
Simulation sim(square);
std::cout<<sim.polygon()->area()<<"\n";
return 0;
}
这工作得很好!然而,它违反了 Simulation
的封装,事实上,如果我从 main
去更改 square
它也会在 Simulation 内部发生变化
。
我正在考虑使用复制构造函数修改 Simulation
的构造函数:
Simulation(Polygon& polygon) { polygon_ = new Polygon(polygon); }
但这意味着我没有多态性...
显然我在这里缺少一些东西...干杯!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
向 Polygon 添加克隆函数(以及虚拟析构函数!)。确保 Polygon 是抽象的是一个好主意,因此确保至少一个函数是纯虚函数。
您的模拟类将需要复制构造函数、析构函数和赋值运算符。
请注意,即使超类返回 Polygon*,Square 克隆函数也可以返回 Square*,因为它是协变的。一些较旧的编译器可能不支持此功能,在这种情况下返回 Polygon*。
Add a clone function to Polygon (and a virtual destructor!). It is a good idea to ensure that Polygon is abstract so make sure at least one function is pure virtual.
Your Simulation class will require a copy constructor, destructor and assignment operator.
Note that the Square clone function can return a Square* even though the super class returns a Polygon* because it is covariant. Some older compilers may not support this, in which case return a Polygon*.
如果
Simulation
包含Polygon
那么这意味着它应该用它来做一些事情。如果您需要直接从“外部”访问多边形,那么您可能错过了某个地方的设计,或者如果没有,您可以使用观察者模式,并让多边形在发生变化时通知模拟。所以,要么:
要么
If
Simulation
containsPolygon
then it means that it is meant to do something with it. If you need to access the polygon directly from the 'outside', you have either missed the design somewhere, or if not, you can use observer pattern and have polygon notify the simulation if something about it changes.So, either:
or
因此,您想确保外部代码无法更改模拟的内部多边形,但又允许在其中使用任何子类?即确保模拟之外没有对 c'tor 中 ref 传递的对象的引用?
您可以考虑一个抽象复制方法来实现这一点:(不要忘记在模拟析构函数中删除)
So you want to make sure that there's no way for outside code to alter the inner polygon of simulation, but yet allow any subclass to be used inside it? I.e. make sure that there are no references outside of simulation to the object passed by ref in the c'tor?
You could think of an abstract copy method to accomplish that: (don't forget to
delete
in simulation destructor)如果要复制多态对象,可以使用克隆方法来完成。
然而,在该示例中,模拟既不对多边形本身执行任何操作,也不想将其分发给其他代码使用,这似乎有点毫无意义。
If you want to copy a polymorphic object, this can be done with a clone method.
However, in the example it seems a bit pointless that the Simulation neither does anything with the polygon itself nor do you want to hand it out for other code to use.
这就是 C++ 的工作原理。如果您为对象(PIMPL)编写包装器,则必须实现其完整接口。这些函数将非常小,只需将调用传递给实际实现,但您必须编写它们。然后你可以改变行为,添加日志记录,或任何你需要的......
That's just how C++ works. If you write a wrapper for an object (PIMPL) you have to implement its full interface. The functions going to be very small just passing the calls to the actual implementation but you have to write them. Then you can alter the behaviour, add logging, or whatever you need...
您只需要确定多边形是在模拟内部还是外部。如果它应该在它之外,那么您就有引用构造函数参数。如果它在里面,您将需要以下代码:
现在,您可以轻松地执行多态性方面的操作,如下所示:
一旦您厌倦了添加新的数据成员,这里有另一个技巧可以修复某些情况:
编辑:请注意顺序头文件中的类的数量需要仔细考虑。
You just need to decide if the polygon is inside or outside of simulation. If it's supposed to be outside of it, then you have reference constructor parameter . If it's inside, you'll need the following code:
Now, the polymorphism aspect you can easily do like this:
And once you get tired to adding new data members, here's another trick which will fix some cases:
Edit: Note that the order of classes in header file needs to be carefully considered.