如何在 C++ 中管理文件唯一 ID
How to manage file unique IDs in c++
c++(不是 c++11)
假设我的项目中有 100 个 .cpp 文件,它们目前正在做一些工作。
所有这些文件目前都包含一些我可以轻松编辑的 globals.h 文件。
我希望这些文件中的每一个都有自己的某个对象实例,并且我还希望该实例具有实例化它的文件的一些唯一 ID。
此外,我希望通过工厂方法创建这些对象,并且我需要实例为用户提供某种方式来处理它们——这意味着它们不能是匿名的。
简而言之——我需要一种方法来为我项目中的所有文件生成唯一的 ID,我需要文件能够在所有文件中使用相同的名称访问它自己的 ID,而且能够在另一个 "manager" 文件中访问外部文件的 ID。
以下选项无效:
1。
枚举:
如果我使用枚举并为每个文件指定一个枚举 ID,现在我无法在 globals.h 中执行此操作:
static thePrivateInstanceInThisFile = theFactory.makeInstance(fileID);
因为我需要在每个文件中使用不同的 fileID
,并且它是静态定义的,并使用我的枚举唯一命名。
2。
Class 计算自己的实例
在globals.h中定义:
class FileIDGiver{
private:
static int currentID;//initialize to 0 in cpp
int myID;
public:
FileIDGiver(){
myID = currentID++;
}
int getFileID(){
return myID;
}
}
static FileIDGiver theFileId;
static thePrivateInstanceInThisFile = theFactory.makeInstance(theFileId.getFileID());
这将为每个静态文件实例提供一个文件唯一的 ID,但现在无法在文件外部对其进行管理。
我考虑过做类似的事情
globals.cpp
int file1ID;
int file2ID;
...
globals.h
extern file1ID;
extern file2ID;
...
file1.cpp
file1ID = theFileId.getFileID();
file2.cpp
file2ID = theFileId.getFileID();
...
每当用户需要管理文件时,他要么使用文件的 ID 变量,要么以上述方式创建一个新文件。
这将允许我从外部访问每个唯一且自动的文件 ID。
我遇到的唯一问题是行 file1ID = theFileId.getFileID();
仅在运行时在行 static thePrivateInstanceInThisFile = theFactory.makeInstance(theFileId.getFileID());
之后执行。
在编译时执行。
我想不出一个好方法来颠倒这个顺序,或者做一个完整的其他机制。
再次 - 我需要:
自动创建的文件 ID
唯一文件 ID(最好是数字)
所有文件中相同变量名对这些 ID 的使用(自动,使用 globals.h 文件中的静态变量定义)
能够使用另一个手动定义的变量手动访问特定文件 ID。
请指教一些完成此任务的好方法
谢谢。
这听起来像是 static initialization order fiasco 的糟糕案例。
这是一个解决方案,它为每个文件唯一分配整数 ID,然后通过使用文件 ID 调用工厂函数生成唯一的 Instance
,同时确保 Instance
工厂在之前初始化它的第一次使用:
idgiver.h
:
class IdGiver
{
int id;
public:
IdGiver() : id(0) {}
int getId() {return id++;}
};
IdGiver &getTheIdGiver();
idgiver.cpp
:
#include "idgiver.h"
IdGiver &getTheIdGiver()
{
static IdGiver theIdGiver;
return theIdGiver;
}
factory.h
:
class Instance
{
// ...
};
class Factory
{
// ...
public:
Factory() : {/*...*/}
Instance getInstance(int id) {/*...*/}
};
Factory &getTheFactory();
factory.cpp
:
#include "factory.h"
Factory &getTheFactory()
{
static Factory theFactory;
return theFactory;
}
globals.h
:
#include "idgiver.h"
#include "factory.h"
static int thisFileId = getTheIdGiver().getId();
static Instance thisFileInstance = getTheFactory().getInstance(thisFileId);
您可以修改您的构建程序(例如您的 Makefile
)来定义一些独特的东西。例如。你可以用类似的东西编译你的 foo23.cpp
文件(假设 GCC 在一些 Linux 系统上;适应你的编译器和 OS 和构建器)
g++ -Wall -c -DBASENAME="$(basename foo23.cpp)" -DUNIQUEID=23
您可以使用一些 shell 脚本或其他任何东西为 UNIQUEID
获得 23,例如Makefile
中的临时规则。详细信息取决于您的文件命名约定。
然后在您的 C 或 C++ 代码中适当地使用 BASENAME
和 UNIQUEID
(可能使用肮脏的 #if UNIQUEID==23
预处理器技巧...)。
所以我的想法是 在您的构建系统中生成 UNIQUEID
并 通过一些预处理器符号 传递它。详细信息是 OS、编译器、构建系统特定的。
您也可以在构建过程中进行一些粗略的 meta-programming by generating some C or C++ source or header file (perhaps using some awk
script or some GPP or m4 预处理。
如果您希望能够访问其他文件的静态 Instance
s,那么这不能通过自动生成的 ID 来完成,因为每次新文件生成时,为文件生成的 ID 可能会更改添加,或者每次编译时,甚至每次执行时。因此,在这个解决方案中,每个文件都手动定义了自己的持久标识,类似于问题中的示例 1。
ids.h
enum FileId
{
File1, File2, File3
};
factory.h
#include "ids.h"
#include "instance.h"
class Factory
{
// ...
public:
Factory() {/*...*/}
Instance createInstance(FileId fileid) {/*...*/}
};
Factory &getTheFactory();
factory.cpp
#include "factory.h"
Factory &getTheFactory()
{
static Factory theFactory;
return theFactory;
}
idmanager.h
#include "ids.h"
#include "instance.h"
template<FileId id>
struct Manager
{
static Instance &getInstance(); // not defined
};
global.h
#include "idmanager.h"
#include "factory.h"
template <>
Instance &Manager<FILEID>::getInstance()
{
static Instance theInstance = getTheFactory().getInstance(FILEID);
return theInstance;
};
static Instance &getThisFileInstance()
{
return Manager<FILEID>::getInstance();
}
用法如下:对于每个需要静态Instance
object的文件,放在开头
#define FILEID File1 // The FileId corresponding to this file
#include "global.h"
然后在任何文件中,
- 唯一 ID 由
FILEID
给出。 (抱歉这是一个宏)
- 这个文件的静态
Instance
是通过getThisFileInstance()
获得的。
- 任何文件的静态
Instance
通过Manager<any_file_id>::getInstance()
获取。
这是通过在每个文件中放置模板 Manager<FileId>
实例化的实现来实现的,每个文件都会创建 returns 该文件的静态 Instance
.
优点是 ID 持久化和零 run-time 开销:不需要动态分配 ID,对 Manager<file_id>::getInstance()
的调用在 compile-time 解析。
此外,ids.h
header 可以很容易地通过扫描每个文件第一行的脚本生成 #define FILEID fileid
,所以唯一剩下的维护就是记住写 #define FILEID fileid
.
c++(不是 c++11)
假设我的项目中有 100 个 .cpp 文件,它们目前正在做一些工作。 所有这些文件目前都包含一些我可以轻松编辑的 globals.h 文件。
我希望这些文件中的每一个都有自己的某个对象实例,并且我还希望该实例具有实例化它的文件的一些唯一 ID。 此外,我希望通过工厂方法创建这些对象,并且我需要实例为用户提供某种方式来处理它们——这意味着它们不能是匿名的。
简而言之——我需要一种方法来为我项目中的所有文件生成唯一的 ID,我需要文件能够在所有文件中使用相同的名称访问它自己的 ID,而且能够在另一个 "manager" 文件中访问外部文件的 ID。
以下选项无效:
1。 枚举:
如果我使用枚举并为每个文件指定一个枚举 ID,现在我无法在 globals.h 中执行此操作:
static thePrivateInstanceInThisFile = theFactory.makeInstance(fileID);
因为我需要在每个文件中使用不同的 fileID
,并且它是静态定义的,并使用我的枚举唯一命名。
2。 Class 计算自己的实例
在globals.h中定义:
class FileIDGiver{
private:
static int currentID;//initialize to 0 in cpp
int myID;
public:
FileIDGiver(){
myID = currentID++;
}
int getFileID(){
return myID;
}
}
static FileIDGiver theFileId;
static thePrivateInstanceInThisFile = theFactory.makeInstance(theFileId.getFileID());
这将为每个静态文件实例提供一个文件唯一的 ID,但现在无法在文件外部对其进行管理。
我考虑过做类似的事情
globals.cpp
int file1ID;
int file2ID;
...
globals.h
extern file1ID;
extern file2ID;
...
file1.cpp
file1ID = theFileId.getFileID();
file2.cpp
file2ID = theFileId.getFileID();
...
每当用户需要管理文件时,他要么使用文件的 ID 变量,要么以上述方式创建一个新文件。
这将允许我从外部访问每个唯一且自动的文件 ID。
我遇到的唯一问题是行 file1ID = theFileId.getFileID();
仅在运行时在行 static thePrivateInstanceInThisFile = theFactory.makeInstance(theFileId.getFileID());
之后执行。
在编译时执行。
我想不出一个好方法来颠倒这个顺序,或者做一个完整的其他机制。
再次 - 我需要:
自动创建的文件 ID
唯一文件 ID(最好是数字)
所有文件中相同变量名对这些 ID 的使用(自动,使用 globals.h 文件中的静态变量定义)
能够使用另一个手动定义的变量手动访问特定文件 ID。
请指教一些完成此任务的好方法
谢谢。
这听起来像是 static initialization order fiasco 的糟糕案例。
这是一个解决方案,它为每个文件唯一分配整数 ID,然后通过使用文件 ID 调用工厂函数生成唯一的 Instance
,同时确保 Instance
工厂在之前初始化它的第一次使用:
idgiver.h
:
class IdGiver
{
int id;
public:
IdGiver() : id(0) {}
int getId() {return id++;}
};
IdGiver &getTheIdGiver();
idgiver.cpp
:
#include "idgiver.h"
IdGiver &getTheIdGiver()
{
static IdGiver theIdGiver;
return theIdGiver;
}
factory.h
:
class Instance
{
// ...
};
class Factory
{
// ...
public:
Factory() : {/*...*/}
Instance getInstance(int id) {/*...*/}
};
Factory &getTheFactory();
factory.cpp
:
#include "factory.h"
Factory &getTheFactory()
{
static Factory theFactory;
return theFactory;
}
globals.h
:
#include "idgiver.h"
#include "factory.h"
static int thisFileId = getTheIdGiver().getId();
static Instance thisFileInstance = getTheFactory().getInstance(thisFileId);
您可以修改您的构建程序(例如您的 Makefile
)来定义一些独特的东西。例如。你可以用类似的东西编译你的 foo23.cpp
文件(假设 GCC 在一些 Linux 系统上;适应你的编译器和 OS 和构建器)
g++ -Wall -c -DBASENAME="$(basename foo23.cpp)" -DUNIQUEID=23
您可以使用一些 shell 脚本或其他任何东西为 UNIQUEID
获得 23,例如Makefile
中的临时规则。详细信息取决于您的文件命名约定。
然后在您的 C 或 C++ 代码中适当地使用 BASENAME
和 UNIQUEID
(可能使用肮脏的 #if UNIQUEID==23
预处理器技巧...)。
所以我的想法是 在您的构建系统中生成 UNIQUEID
并 通过一些预处理器符号 传递它。详细信息是 OS、编译器、构建系统特定的。
您也可以在构建过程中进行一些粗略的 meta-programming by generating some C or C++ source or header file (perhaps using some awk
script or some GPP or m4 预处理。
如果您希望能够访问其他文件的静态 Instance
s,那么这不能通过自动生成的 ID 来完成,因为每次新文件生成时,为文件生成的 ID 可能会更改添加,或者每次编译时,甚至每次执行时。因此,在这个解决方案中,每个文件都手动定义了自己的持久标识,类似于问题中的示例 1。
ids.h
enum FileId
{
File1, File2, File3
};
factory.h
#include "ids.h"
#include "instance.h"
class Factory
{
// ...
public:
Factory() {/*...*/}
Instance createInstance(FileId fileid) {/*...*/}
};
Factory &getTheFactory();
factory.cpp
#include "factory.h"
Factory &getTheFactory()
{
static Factory theFactory;
return theFactory;
}
idmanager.h
#include "ids.h"
#include "instance.h"
template<FileId id>
struct Manager
{
static Instance &getInstance(); // not defined
};
global.h
#include "idmanager.h"
#include "factory.h"
template <>
Instance &Manager<FILEID>::getInstance()
{
static Instance theInstance = getTheFactory().getInstance(FILEID);
return theInstance;
};
static Instance &getThisFileInstance()
{
return Manager<FILEID>::getInstance();
}
用法如下:对于每个需要静态Instance
object的文件,放在开头
#define FILEID File1 // The FileId corresponding to this file
#include "global.h"
然后在任何文件中,
- 唯一 ID 由
FILEID
给出。 (抱歉这是一个宏) - 这个文件的静态
Instance
是通过getThisFileInstance()
获得的。 - 任何文件的静态
Instance
通过Manager<any_file_id>::getInstance()
获取。
这是通过在每个文件中放置模板 Manager<FileId>
实例化的实现来实现的,每个文件都会创建 returns 该文件的静态 Instance
.
优点是 ID 持久化和零 run-time 开销:不需要动态分配 ID,对 Manager<file_id>::getInstance()
的调用在 compile-time 解析。
此外,ids.h
header 可以很容易地通过扫描每个文件第一行的脚本生成 #define FILEID fileid
,所以唯一剩下的维护就是记住写 #define FILEID fileid
.