我想注册给定类的所有对象,以便稍后我可以拥有迭代它们的静态方法。我想出了下面的解决方案。我的想法是,我将向与我一起工作的其他人提供此类,他们将派生该类来设计自己的模块。但是,我必须将指针数组初始化为大尺寸,因为我不知道将创建多少个该对象。如果所有对象都是静态声明的,有什么方法可以在编译时找出创建的对象的数量吗?
class Module {
static Module* module_list[];
static int count;
public:
Module(string str){
id = count;
name = str;
module_list[count++] = this;
}
static void printModules(){
for(int i = 0; i < count; i++)
cout << module_list[i]->name << endl;
}
int id;
string name;
};
Module* Module::module_list[256];
int Module::count = 0;
Module x("module x"), y("module y");
int main(){
Module::printModules();
}
注意:我最初的目标是在编译时创建列表本身,但是,我不知道如何做到这一点。欢迎提出建议。
有什么方法可以在编译时找出创建的对象的数量(如果它们都是静态声明的)?
并非如此,因为对象可能在单独的翻译单元中实例化。即使不是,目前也无法反映特定的翻译单元并在 C++ 中查找特定对象的所有实例化(除非您想使用外部解析器+代码生成器解决方案)。
但是,我必须将指针数组初始化为大尺寸,因为我不知道将创建多少个该对象。
只需使用
std::vector
,因此您不需要任何固定限制:
auto& getModuleList()
{
static std::vector<Module*> result;
return result;
}
class Module {
public:
Module(string str){
id = count;
name = str;
getModuleList().emplace_back(this);
}
要在进程启动时访问多个编译单元中定义为函数静态的结构的所有实例,请在结构定义中包含一个幻数。然后,在进程启动时,扫描加载的可执行文件以找到幻数。从每个幻数地址确定相应结构的起始地址。为了降低误报的风险,请将所有结构放在它们自己的链接器部分中,并仅扫描该部分。 g++ 可能有一个小问题,这会导致一些定义出现编译错误。我从来没有弄清楚是什么原因造成的。解决方法是使用多个按顺序编号的链接器部分。翻译单元中的第 N 个定义位于第 N 个链接器部分中,因此链接器部分的数量与翻译单元中定义的最大数量一样多。通过使用预处理器自动化将每个定义放入链接器部分所需的样板,保持代码整洁。如果使用解决方法,请使用预处理器宏
__COUNTER__
作为节名称的一部分。