1

我目前正在为我的项目设计一些课程,C++但我遇到了问题。我想创建一个camera包含所有需要的值(例如转换矩阵)的类,但呈现的函数camera应该是可交换的。这听起来像是策略模式的常见情况。因此,我创建了一个接口,该接口定义了该接口render-function并将camera类 apointer赋予该接口。问题是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;
};

camera->renderCamera()由于无限循环的责任(调用in ) 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 函数。您如何看待这个解决方案?

问候斯坦

4

2 回答 2

3

你是对的,这似乎是一个糟糕的设计。:)

我不明白为什么相机渲染需要访问相机。我确定您可以将其他内容作为参数传递。渲染不需要访问所有相机成员,因此您可以传递它需要的那些(如果有很多,请将它们包装在一个结构CameraConfig或类似的东西中)。

如果不同的渲染需要不同的参数,您可以使用ICameraConfig.

于 2012-09-28T08:30:23.403 回答
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 给您带来的一些好处。它会真正清理您的代码并使其更安全。(尤其是共享/唯一/等 ptr 类。)

于 2012-09-28T17:23:06.413 回答