背景信息
我目前正在上计算机图形学类(class)。我们学习主要概念的方式是通过制作任何人都可以使用的抽象(又名简单的 3D 库)。我们将 SDL 用于真正的图形部分。实际上,我们使用 SDL 的目的只是渲染和操作像素缓冲区。我们只被允许使用那个。但是我们的抽象应该允许客户端绘制像素、线、三角形等,一直到完成由这些三角形组成的模型。
事情进展得很顺利……直到教授看了看我的抽象。他说这不是很面向对象。
我的问题
我不是在寻找对我的代码的审查,而是在寻找有关如何使用可靠的面向对象原则设计此 SDL 库的一些一般性意见和建议。
到目前为止我有什么
我的代码实际上很好地利用了一些面向对象的原则。到目前为止,我有以下对象工作正常:
- Vec4 - 代表坐标或颜色。它执行与 vector 相关的操作。
- 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 循环,其中我做了两件事:
- 调用任何已注册的回调
- 在存储所有形状的 vector 中绘制形状
但是这样不好。如果我插入 10 个三角形,它们都画得很好。但是如果我想旋转一个特定的对象,我不能这样做,因为我的回调只允许我从 main 访问我的 RDL 对象。
有什么想法、提示或一般建议吗?
非常感谢。我知道这是一个很长的问题...
最佳答案
您的回调是普通的旧函数。这就是他们的问题所在。想象一下你只能有没有参数的函数。或具有固定类型的一个参数的函数。你不会做得太过分。但是你的回调就是那样。
您希望能够将一个函数及其参数传递给您的RegisterXyzEvent()
。时机成熟时,您的框架应该使用提供的参数调用该函数。
在 C++ 中调用与其(某些)参数捆绑在一起的函数 - 称为“绑定(bind)函数”或“函数对象”,有时也称为“仿函数”(最后一个是一个非常错误的名称,不幸的是卡住了)。您需要了解这些绑定(bind)函数的工作原理、如何构建它们、如何使用标准库附带的函数以及如何推出您自己的函数。然后让 RegisterXyzEvent()
接受这样的函数对象,并让你的框架调用它们。
要搜索的一些关键字:函数对象、boost::bind、std::function。
抱歉没有示例的简短回答。我的手机键盘很烦人,我认为你最好还是在自己的网上学习这些东西。
关于c++ - 面向对象的 C++ 抽象架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8958226/