函数的单个实例
single instance of a function
我正在做一个C++项目(Embarcadero C++ Builder),其中许多类(都在同一个命名空间中)需要从颜色名称中获取颜色值。为了实现这一点,我在一段单独的代码 Tools.cpp 中创建了一个所有类使用的函数 getColorCode(),如下所示:
#include "Tools.h"
namespace mynamespace {
int getColorCode(std::string Name)
{
if (Name == "red") return(0xFF0000);
else if (Name == "green") return(0x00FF00);
else if (Name == "blue") return(0x0000FF);
// many more else ifs
else return(0x000000);
}
}
头文件是:
#ifndef MYNAMESPACE_TOOLS_H
#define MYNAMESPACE_TOOLS_H
#include <string>
namespace mynamespace {
int getColorCode(std::string Name);
}
#endif
这有效,但我希望将所有颜色定义存储在地图中,以避免数百个其他 if。我的问题是,我无法在工具的头文件中定义类似std::map<std::string, int> ColorNames;
的东西.cpp而不会W8058 Cannot create pre-compiled header
定义地图的行。此外,我收到几个链接器警告,指出mynamespace::ColorNames在每个类中都定义,包括Tools.h。
我的计划是通过检查 map.empty() 在第一次调用 getColorCode() 时填充地图,如果它是空的,则添加所有颜色名称和代码,因此进一步的调用将只搜索地图。
另一个尝试是为此创建一个工具类并在构造函数中初始化映射。但是每个使用它的类都会创建一个自己的实例,这是我不想要的。阅读有关单例的讨论并尝试提出的代码无济于事。
有什么实用的方法来实现这一点,或者让我留在丑陋的(非性能的)if-then-else 链上?
感谢您的任何提示,阿明
如果你可以使用 C++11(我不熟悉 C++-builder),你可以像这样在函数中初始化静态映射
int getColorCode(std::string name) {
static std::map<std::string, int> colors{
{ "red", 0xFF0000 },
{ "green", 0x00FF00 },
// ... etc
};
// rest of logic.
}
这样做的好处是映射已本地化到函数中,初始化一次且仅初始化一次,并且无法从外部世界访问。
如果您没有 C++11 个功能(同样,我不知道编译器),只需检查地图是否像您所说的那样为空,然后填充它。不过,我仍然会将其标记为静态,全局变量很糟糕。
文件级静态接缝在这里适合我,但您需要在初始化时处理竞争条件。 但是,我可能会建议只为颜色名称创建宏,这些宏会被 int 替换。 或者一个具有所有常量模因的类
文件级静态
static std::map<string,int> Colors;
static std::mutex lck;
int getColorCode(std::string Name)
{
// Get a lock here if you are not single threaded
lck.lock()
if(Colors.empty())
{...}
lck.unlock()
}
或具有所有颜色的类
class Colors
{
Colors():
red(0xFF0000)
{
}
int red;
}
我会使用一个简单的struct
声明而不是地图。只要您没有数百万个条目,这就不会真正让您在使用std::map
时对性能产生重大影响。检查 O(n) 与 O(log n) 的复杂性是否适合您对 n 个条目的需求,但我认为数百个范围内的 n(如您提到的)也不应该如此。
就在你.cpp里面做:
namespace {
struct ColorDef
{
std::string name;
int colorValue;
};
ColorDef colorValueDefs[] = {
// Put your entries here:
{ "red", 0xFF0000 } ,
{ "green", 0x00FF00 } ,
{ "blue", 0x0000FF } ,
// etc. ...
// { "" , -1 } // have an end marker if you don't want to use sizeof()
// to iterate through
};
}
namespace mynamespace {
int getColorCode(std::string Name) {
// Make it thread safe if necessary:
// static std::mutex mtx;
// std::lock(mtx);
for(int i = 0; i < sizeof(colorValueDefs); ++i) {
if(Name == colorValueDefs[i].name) {
return colorValueDefs[i].colorValue;
}
}
return -1;
}
}
如果可以使用 c++11 标准语法,则可以使用与上面所示的colorValueDefs
数组相同的方式初始化std::map
。
更新
好吧,我想我一直在这里胡说八道!如果我正确获取图表,则在 n 的数量非常少时开始出现性能影响,请检查图表:n = 10
我不确定在这里获得 O(n)/O(log n) 的正确表示:-/...
std::map
应该是更好的选择,然后是性能明智的选择!在第一次调用函数时初始化时,你会受到一个小影响,或者在使用 c++11 初始值设定项列表功能初始化映射时可以避免这种情况。
只需将映射放在源文件中,然后使用该函数从中检索值:
#include "Tools.h"
namespace mynamespace {
std::map<std::string, int> ColorNames;
int getColorCode(std::string Name)
{
// do some error checking
// assume ColorNames has already been populated somehow
return ColorNames[Name];
}
}
- 多个 rocksdb 实例:使用单个共享缓存还是多个独立缓存?
- c++ 是否保证标头初始化的静态 const 成员跨编译单元和库共享单个实例?
- 通过单个实例从多个类访问一个类
- 如何在C++中调试单个容器实例的大小
- 传递单个或向量对象时没有重载函数的实例
- Qt - 打开窗口的单个实例
- 如何在崩溃时管理Qt应用程序的单个实例
- C++ 使用单个输入字节文件的不同部分实例化堆栈上的成员类
- 函数的单个实例
- cout 对象是否保持单个实例,即它永远不会被复制
- C++程序的单个实例,使用boost::interprocess
- 许多QPropertyAnimation实例与单个实例相比
- 每个层次结构的单个单一实例继承
- 最大化qt中单个实例应用程序的已运行实例
- Qt new-多个实例或指向单个实例的指针
- 为C++中模板的所有实例生成的单个机器代码实例:它是否可行和/或可能
- 对于单个实例应用程序,只允许使用单个窗口消息框
- 单个类实例在GUI exe和dll中是不同的
- 如何按值从vector中删除元素,但只能删除该值的单个实例
- 单独对象的单个模板实例化