【发布时间】:2017-12-22 11:12:28
【问题描述】:
我正在使用 SFML 创建一个 Snake 游戏,并且我有一个具体的类 SnakeGame 包含我的类的所有数据成员,例如窗口大小、游戏地图的大小、蛇的颜色等。因此,我班级的内部成员如下所示:
class SnakeGame
{
private:
//....
const sf::Vector2u windowSize{400, 336};
const sf::Color snakeColor {0, 0, 0};
//...etc...
public:
SnakeGame() :
renderWindow {sf::VideoMode{windowSize.x, windowSize.y}, /*other arguments*/ },
snake {snakeColor, /*other arguments*/}
/*etc*/
{}
但是,这不起作用,我得到一个不可见的窗口,让我相信这些论点尚未构建。在阅读了另一篇 SO 帖子后,我读到 const 成员作为类的成员不会在编译时评估,而是在运行时实例化类时评估,并且它们的行为方式与 const 变量完全相同。因此,当我在main 中实例化SnakeGame 时,会评估变量windowSize 和snakeColor,因此我不能在我的类的初始化程序列表中使用它们。为了尝试解决这个困境,我决定切换到static constexpr 变量,但不幸的是我意识到sf::Vector<T> 没有constexpr 构造函数,sf::Color 也没有。当然,我想我可以切换到整数类型,例如窗口大小的static constexpr unsigned int,但最终这会变得重复,尤其是对于颜色。所以我决定走另一条路。我所做的是创建另一个文件GameData.hpp,并在其中执行此操作:
namespace gd //For game data
{
const sf::Vector2u windowSize{400, 336};
const sf::Color snakeColor {0, 0, 0};
//...etc...
}
但是,我不喜欢这种解决方案,因为即使现在在编译时评估此数据,如果它们包含适当的头文件,我的所有类也可以访问它,而不仅仅是SnakeGame。这样一来,我觉得我班级的内部数据结构正在被揭示。这导致了我的问题,即:有没有办法强制 const 类的成员在编译时进行评估,这样这些变量可以在初始化列表中使用,并保证它们会建好了吗?
【问题讨论】:
-
你为什么不简单地使用
static成员(非constexpr)? -
或以正确的顺序重新排列您的成员。
-
您还可以根据它们将这些字段的声明移到字段声明之上,因为类字段是按照您声明它们的顺序构造的。
-
@JérémiPanneton 我会这样做,但我想初始化类中的成员。
-
@Jarod42 我已经按照你说的做了,而且有效!谢谢!
标签: c++ c++11 constants sfml compile-time