我正在为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;
};
由于对infity循环(在camera->renderCamera()
中的render-function
中调用ICameraRender
)的责任,这似乎不是一个优雅的解决方案。这个问题有更好的解决方案吗?
此致
编辑:
我提出了另一个解决方案。由于操作相机数据的功能,只需要访问我认为可以拆分相机类本身的数据。一个名为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功能。 您对此解决方案有何看法?
问候斯坦
答案 0 :(得分:3)
你是对的,看起来确实是一个糟糕的设计。 :)
我不明白为什么相机渲染需要访问相机。我相信你可以传递其他东西作为参数。渲染不需要访问所有摄像机成员,因此您可以传递它所需的那些(并且,如果有很多它们,将它们包装在结构CameraConfig
或类似的东西中)。
如果不同的渲染需要不同的参数,您可以使用ICameraConfig
创建单独的层次结构。
答案 1 :(得分:2)
这可能是使用基于策略的设计来实现策略模式的好时机,特别是因为你正在使用C ++而你可能的目标是早于2002年的编译器。(由于C ++的模板机制非常棒,我们可以通过这种方式免费获得策略模式!)
首先:让您的类在模板参数中接受策略/策略类(在本例中为ICameraRenderer)。然后,指定您使用该模板参数中的某个方法。在相机类中调用该方法......
然后使用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为您提供的一些优点。它会真正清理你的代码并使其更安全。 (特别是shared / unique / etc ptr类。)