【问题标题】:Object Oriented C++ Abstraction Architecture面向对象的 C++ 抽象架构
【发布时间】:2012-01-22 10:19:58
【问题描述】:

背景信息

我目前正在上计算机图形课程。我们学习主要概念的方式是制作一个任何人都可以使用的抽象(也就是一个简单的 3D 库)。我们将 SDL 用于真实的图形部分。实际上,我们使用 SDL 只是为了渲染和操作像素缓冲区。我们只被允许使用它。但是我们的抽象应该允许客户端一直绘制像素、线条、三角形等,以完成由这些三角形组成的模型。

事情进展得很顺利……直到教授看了我的抽象。他说这不是非常面向对象的。

我的问题

我并不是在寻找对我的代码的审查,而是在寻找一些关于如何使用健全的面向对象原则设计这个 SDL 库的一般性建议和建议。

我目前所拥有的

我的代码实际上很好地利用了一些面向对象的原则。到目前为止,我有以下对象工作正常:

  • Vec4 - 表示坐标或颜色。它执行与向量相关的操作。
  • Mat4 - 表示我用于转换等的 4x4 矩阵。是否与矩阵相关的操作,例如乘以另一个矩阵、乘以 vec4 等。
  • MatrixFactory - 创建不同类型的 Mat4(MatrixTranslate、MatrixRotate 等)
  • Shape - 用于更轻松地绘制各种形状的界面
    • 点:形状
    • 线条:形状
    • 三角形:形状

我的“引擎”本身执行以下操作(在某种程度上基于three.js 结构):

  • 创建一个窗口(绘制事物的主窗口)
  • 创建一个场景(显示形状的地方)
  • 根据键盘事件(按键)注册回调函数

我正在特别挣扎的地方

到目前为止,我正在努力解决的主要问题是处理回调。例如,要绘制一个三角形,我目前执行以下操作:

int main()
{
    // Create instance of my library
    RDL* rdl = new RDL(WIDTH, HEIGHT, 32); 


    // Draw a triangle when T is pressed
    // RDL_KEY_t = #define RDL_KEY_t SDLK_t for consistency 
    rdl->registerKeyEvent(RDL_KEY_t, drawTriangle);

    rdl->show();

    return 0;
}


// X, Y, Z and R, G, B are random values not shown for simplicity
void drawTriangle(RDL* rdl)
{
    RDL_Point p1(Vec4(X, Y, Z), Vec4(R, G, B));
    RDL_Point p2(Vec4(X, Y, Z), Vec4(R, G, B));
    RDL_Point p3(Vec4(X, Y, Z), Vec4(R, G, B));

    rdl->insertShape(RDL_Triangle(pt1, pt2, pt3));
}

在 RDL::show() 内部,我运行标准 SDL 循环,我在其中做两件事:

  • 调用任何注册的回调
  • 在存储所有形状的矢量中绘制形状

但这并不好。如果我插入 10 个三角形,它们都画得很好。但是如果我想旋转一个特定的,我不能这样做,因为我的回调只允许我从 main 访问我的 RDL 对象。

有什么想法、提示或一般建议?

非常感谢。我知道这是一个很长的问题...

【问题讨论】:

  • 这个网站更适合:codereview.stackexchange.com
  • 另外,你为什么使用new?这是 C++,不是 Java。
  • @brendanw 这就是你如何避免在 C++ 中构造对象
  • 在这种特殊情况下,它甚至重要吗?
  • @EqSum 鉴于您的示例代码永远不会调用 RDL 的析构函数,这可能会做一些重要的事情(序列化状态等):是的。

标签: c++ oop architecture callback sdl


【解决方案1】:

您的回调是普通的旧函数。这就是他们的问题。想象一下,你只能有没有参数的函数。或者具有一个固定类型参数的函数。你不会走得太远。但是你的回调就是这样的。

您希望能够将函数传递给您的RegisterXyzEvent()。时机成熟时,您的框架应该使用提供的参数调用该函数。

与(某些)参数捆绑在一起的函数在 C++ 中被称为“绑定函数”或“函数对象”或有时是“函子”(最后一个是一个非常错误的名称,不幸的是被卡住了)。您需要了解这些绑定函数是如何工作的,如何构建它们,如何使用standsrd 库附带的函数,以及如何使用自己的函数。然后让RegisterXyzEvent() 接受这样的函数对象,并让你的框架调用它们。

一些要搜索的关键字:函数对象、boost::bind、std::function。

抱歉,没有示例的简短回答。我的手机键盘很烦人,我认为你最好还是自己学习这些东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 2019-03-24
    • 1970-01-01
    相关资源
    最近更新 更多