目前,我正在为我的C++项目设计一些类,但我遇到了一个问题。我想创建一个camera类,它包含所有需要的值(例如,转换矩阵),但是呈现camera的函数应该是可交换的。这听起来像是策略模式的常见情况。因此,我创建了一个定义render-function的接口,并为camera类提供了该接口的pointer。问题是render function需要访问camera类中的所有数据,因此我给这个函数一个指向camera类的指针作为参数。它看起来是这样的:
#include "ICameraRender.h"
class Camera{
private:
ICameraRender* _cameraRender;
public:
Camera();
Camera(ICameraRender& cameraRender);
~Camera();
void renderCamera(){ _cameraRender->render(this); }
void setCameraRender(ICameraRender& cameraRender);
/..../
};
class ICameraRender{
public:
virtual ~ICameraRender(){
}
//Override me
virtual void render(Camera* camera) = 0;
};这似乎不是一个优雅的解决方案,因为容易出现初始循环(在ICameraRender中的render-function中调用camera->renderCamera() )。这个问题有没有更好的解决方案?
问候
编辑:
我想出了另一个解决方案。由于操作相机数据的函数只需要访问数据,我认为我可以拆分相机类本身。一个名为Camera和CameraModel的类。最后一个保存所有需要的数据,第一个对其进行操作。因此,我只需将指向CameraModel的指针传递给我的函数:
class CameraModel{
private:
/...data.../
public:
/...setter and getter.../
};
class Camera{
private:
CameraModel* _cameraModel;
ICameraRender* _cameraRender;
public:
Camera();
Camera(ICameraRender& cameraRender);
~Camera();
void renderCamera(){ _cameraRender->render(_cameraModel); }
void setCameraRender(ICameraRender& cameraRender);
/..../
};
class ICameraRender{
public:
virtual ~ICameraRender(){
}
//Override me
virtual void render(CameraModel* cameraModel) = 0;
};现在,渲染函数(仅根据用户输入计算摄影机的新值)不再具有对renderCamera函数的访问权限。你对这个解决方案有什么看法?
致敬Stan
发布于 2012-09-28 16:30:23
你说得对,这看起来确实是个糟糕的设计。:)
我不明白为什么摄影机渲染需要访问摄影机。我相信你可以传递一些其他的东西作为参数。渲染器不需要访问所有的摄影机成员,因此您可以只传递它需要的成员(如果它们很多,则将它们包装在一个结构CameraConfig或类似的东西中)。
如果不同的渲染需要不同的参数,可以使用ICameraConfig创建单独的层次。
发布于 2012-09-29 01:23:06
这可能是使用基于策略的设计来实现策略模式的好时机,特别是因为您使用的是C++,而且您的目标编译器可能早于2002年。(由于C++的模板机制非常棒,我们可以通过这种方式免费获得策略模式!)
首先:让您的类在模板参数中接受策略/策略类(在本例中是您的ICameraRenderer)。然后,指定您正在使用该模板参数中的某个方法。在camera类中调用该方法...
然后使用render()方法将您的策略实现为一个普通的老类!
这看起来像这样:
class Camera<RenderStrategy>{
using RenderStrategy::render;
/// bla bla bla
public:
void renderCamera(){ render(cameraModel); }
};
class SpiffyRender{
public:
void render(CameraModel orWhateverTheParameterIs){ // some implementation goes somewhere }
};当您想要制作使用这些策略/策略之一的摄像机时:
// the syntax will be a bit different, my C++ chops are rusty;
// in general: you'll construct a camera object, passing in the strategy to the template parameter
auto SpiffyCamera = new Camera<SpiffyRender>();(由于您的渲染器策略没有任何状态,这使得这种方法更加有利)
如果你一直在改变你的渲染器,那么这种模式/方法就变得不那么有利了……但是如果你有一个总是以相同的方式渲染的摄影机,这是一个稍微好一点的方法。如果你的呈现器有状态,你仍然可以使用这个方法;但是你需要一个对类内部实例的引用,并且你不会使用Using::语句。(通常,使用这种方法,您可以编写更少的样板文件,不需要在运行时进行任何赋值或分配,并且编译器可以为您工作)
有关这方面的更多信息,请参阅:http://en.wikipedia.org/wiki/Policy-based_design或阅读现代C++设计...无论如何,这是一个很棒的读物!http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315
顺便说一句:您可能想了解一下C++x11给您带来的好处。它真的会清理你的代码,让它更安全。(尤其是共享/唯一/etc ptr类。)
https://stackoverflow.com/questions/12636312
复制相似问题