我正在开发一款游戏,有一个有趣的问题。我想在一个文件中实现一些游戏范围的常量值。现在我有这样的事情:
常量.cpp
extern const int BEGINNING_HEALTH = 10;
extern const int BEGINNING_MANA = 5;
常量.hpp
extern const int BEGINNING_HEALTH;
extern const int BEGINNING_MANA;
然后文件只是#include“constants.hpp” 这非常有效,直到我需要使用其中一个常量作为模板参数,因为外部链接常量不是有效的模板参数。 所以我的问题是,实现这些常量的最佳方法是什么?恐怕简单地将常量放入头文件中会导致它们在每个翻译单元中定义。而且我不想使用宏。
谢谢
摆脱
extern
就可以了。
此代码在标头中运行得非常好,因为一切都是“真正恒定的”,因此具有内部链接:
const int BEGINNING_HEALTH = 10;
const int BEGINNING_MANA = 5;
const char BEGINNING_NAME[] = "Fred";
const char *const BEGINNING_NAME2 = "Barney";
此代码不能安全地放入头文件中,因为每一行都有外部链接(无论是显式的还是因为不是真正恒定的):
extern const int BEGINNING_HEALTH = 10;
extern const int BEGINNING_MANA = 5;
const char *BEGINNING_NAME = "Wilma"; // the characters are const, but the pointer isn't
枚举怎么样?
常量.hpp
enum {
BEGINNING_HEALTH = 10,
BEGINNING_MANA = 5
}
在您的 .hpp 文件中使用“static const int”,并且在 .cpp 文件中不放置任何内容(当然,您在那里拥有的任何其他代码除外)。
利用命名空间:
namespace GameBeginning {
const int HEALTH = 10;
const int MANA = 5;
};
然后你可以使用player.health = GameBeginning::HEALTH;
大多数编译器根本不为 const POD 值分配空间。他们优化了它们并将它们视为已经被
#define
d,不是吗?
一个简单的人发生了什么:
#define BEGINNING_HEALTH 10
伙计,那些日子。
哦等等,那些仍然是的日子!
要在@2024年更新这篇文章,特别是如果使用
-std=c++17
(及以上),在标头中定义const
并跨文件共享它会导致在您包含的每个单独文件中拥有相同变量的多个独立副本那个标题。这是因为 const 全局变量具有内部链接,因此链接器无法看到它们。与下面的方法相比,这使得它成为一种效率较低的方法......
相反,正如 @Alex 在 www.learncpp.com/Sharing Global Constants across multiple files 中所建议的那样,您可以使用
inline
关键字将全局常量定义为 constexpr
变量,并在命名空间中定义它们,例如:
//constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
// define your own namespace to hold constants
namespace constants
{
inline constexpr int beginning_health { 10 };
inline constexpr int beginning_mana { 5 };
// ... other related constants
}
#endif
//main.cpp
#include "constants.h"
#include <iostream>
int main()
{
std::cout << "Starting health: " << constants::beginning_health << '\n';
std::cout << "Starting mana: " << constants::beginning_mana << '\n';
return 0;
}
这样,这些变量只会实例化一次并在所有代码文件之间共享,从而避免 ODR 违规和重复。现在,每次更改全局常量时,包含它们的相关文件都将重新编译,以在构建时间中重新推导这些值。
也许类似于静态类?
class CONSTANTS {
public:
static inline int getMana() { return 10;};
};
作为标题问题的快速回答,单例模式可能是定义跨文件常量并确保对象只有一个实例的最佳 C++ 方法。
就模板参数问题而言,您需要传递类型而不是值。 您的类型是“int”。