具有静态成员的 C++ 注册模式有效 "sometimes"
C++ register pattern with static member works "sometimes"
我正在尝试在运行时实现自动 class 注册(我认为这种技术属于 "register pattern" 的名称)。在下面的示例中,我将 int
存储在静态成员向量中,但目标是存储以后可以调用的函数指针。
我的理解是,由于我下面代码中的成员 registeredClasses
被声明为 static
,所以在整个程序中应该只有一个它的实例。然而,情况似乎并非如此:
classregister.h
#ifndef CLASSREGISTER_H
#define CLASSREGISTER_H
#include <vector>
#include <iostream>
class ClassRegister
{
public:
static std::vector<int> registeredClasses; //declaration
ClassRegister(int id) {
std::cerr << "registering " << id << " ";
registeredClasses.push_back(id);
std::cerr << "new size: " << registeredClasses.size() << "\n";
}
//code below just for testing
ClassRegister() {}
static int getSize() {
return registeredClasses.size();
}
};
#define REGISTER_CLASS(cls) \
static ClassRegister myClass_##cls(1);
#endif // CLASSREGISTER_H
classregister.cpp
#include "classregister.h"
std::vector<int> ClassRegister::registeredClasses; //definition
class1.h(class2.h遵循相同的模式,为简洁起见省略)
#ifndef CLASS1_H
#define CLASS1_H
#include "classregister.h"
class Class1
{
public:
Class1();
};
REGISTER_CLASS(Class1)
#endif // CLASS1_H
class1.cpp(class2.cpp遵循相同的模式,为简洁起见省略)
#include "class1.h"
Class1::Class1()
{
}
main.cpp
#include "classregister.h"
#include <iostream>
int main(int argc, char *argv[])
{
std::cerr << "registering classes works...\n\n";
std::cerr << "but reading from main() does not...\n";
std::cerr << "checking size directly: " << ClassRegister::registeredClasses.size() << "\n";
std::cerr << "checking size through function: " << ClassRegister::getSize() << "\n";
std::cerr << "checking size on instance: " << ClassRegister().getSize() << "\n";
std::cerr << "\n";
std::cerr << "registration from main() uses a different register...\n";
ClassRegister(2);
ClassRegister(3);
ClassRegister(4);
std::cerr << "\n";
std::cerr << "...which is not the one used in the header files\n";
std::cerr << "checking size directly: " << ClassRegister::registeredClasses.size() << "\n";
std::cerr << "checking size on instance: " << ClassRegister().getSize() << "\n";
std::cerr << "checking size through function: " << ClassRegister::getSize() << "\n";
std::cerr << "\n";
}
我遇到的问题是它只能工作 "sometimes"。初始输出:
registering 1 new size: 1
registering 1 new size: 2
registering classes works...
but reading from main() does not...
checking size directly: 0
checking size through function: 0
checking size on instance: 0
registration from main() uses a different register...
registering 2 new size: 1
registering 3 new size: 2
registering 4 new size: 3
...which is not the one used in the header files
checking size directly: 3
checking size on instance: 3
checking size through function: 3
我删除了 class1.cpp 和 class2.cpp,在头文件中声明构造函数,例如。 Class1() {}
。注册根本不起作用:
//no output here
registering classes works...
//...
然后我恢复了更改,突然我得到了预期的输出:
registering 1 new size: 1
registering 1 new size: 2
registering classes works...
but reading from main() does not... //it does work this time
checking size directly: 2
checking size through function: 2
checking size on instance: 2
registration from main() uses a different register...
registering 2 new size: 3
registering 3 new size: 4
registering 4 new size: 5
...which is not the one used in the header files
checking size directly: 5
checking size on instance: 5
checking size through function: 5
我一直在研究这个问题,但未能弄清原因。我的猜测是它与编译顺序(但注册如何工作?)或 linkage / storage duration 有关。有人可以解释一下吗?
当你实现自动class注册方案时,你应该注意静态初始化顺序,多线程。
删除 .cpp 文件后它不起作用的原因是头文件未编译,因此没有人知道有任何声明。
我认为您在这里需要的技巧是 ClassRegister
而不是静态数据成员,而是使用具有静态局部变量的函数。这有时被称为单例,虽然我不知道这是否真的是正确的术语。
代码可能如下所示:
typedef std::vector<int> register_type;
register_type& getRegister() {
static register_type registeredClasses; //declaration
return registeredClasses;
}
我正在尝试在运行时实现自动 class 注册(我认为这种技术属于 "register pattern" 的名称)。在下面的示例中,我将 int
存储在静态成员向量中,但目标是存储以后可以调用的函数指针。
我的理解是,由于我下面代码中的成员 registeredClasses
被声明为 static
,所以在整个程序中应该只有一个它的实例。然而,情况似乎并非如此:
classregister.h
#ifndef CLASSREGISTER_H
#define CLASSREGISTER_H
#include <vector>
#include <iostream>
class ClassRegister
{
public:
static std::vector<int> registeredClasses; //declaration
ClassRegister(int id) {
std::cerr << "registering " << id << " ";
registeredClasses.push_back(id);
std::cerr << "new size: " << registeredClasses.size() << "\n";
}
//code below just for testing
ClassRegister() {}
static int getSize() {
return registeredClasses.size();
}
};
#define REGISTER_CLASS(cls) \
static ClassRegister myClass_##cls(1);
#endif // CLASSREGISTER_H
classregister.cpp
#include "classregister.h"
std::vector<int> ClassRegister::registeredClasses; //definition
class1.h(class2.h遵循相同的模式,为简洁起见省略)
#ifndef CLASS1_H
#define CLASS1_H
#include "classregister.h"
class Class1
{
public:
Class1();
};
REGISTER_CLASS(Class1)
#endif // CLASS1_H
class1.cpp(class2.cpp遵循相同的模式,为简洁起见省略)
#include "class1.h"
Class1::Class1()
{
}
main.cpp
#include "classregister.h"
#include <iostream>
int main(int argc, char *argv[])
{
std::cerr << "registering classes works...\n\n";
std::cerr << "but reading from main() does not...\n";
std::cerr << "checking size directly: " << ClassRegister::registeredClasses.size() << "\n";
std::cerr << "checking size through function: " << ClassRegister::getSize() << "\n";
std::cerr << "checking size on instance: " << ClassRegister().getSize() << "\n";
std::cerr << "\n";
std::cerr << "registration from main() uses a different register...\n";
ClassRegister(2);
ClassRegister(3);
ClassRegister(4);
std::cerr << "\n";
std::cerr << "...which is not the one used in the header files\n";
std::cerr << "checking size directly: " << ClassRegister::registeredClasses.size() << "\n";
std::cerr << "checking size on instance: " << ClassRegister().getSize() << "\n";
std::cerr << "checking size through function: " << ClassRegister::getSize() << "\n";
std::cerr << "\n";
}
我遇到的问题是它只能工作 "sometimes"。初始输出:
registering 1 new size: 1
registering 1 new size: 2
registering classes works...
but reading from main() does not...
checking size directly: 0
checking size through function: 0
checking size on instance: 0
registration from main() uses a different register...
registering 2 new size: 1
registering 3 new size: 2
registering 4 new size: 3
...which is not the one used in the header files
checking size directly: 3
checking size on instance: 3
checking size through function: 3
我删除了 class1.cpp 和 class2.cpp,在头文件中声明构造函数,例如。 Class1() {}
。注册根本不起作用:
//no output here
registering classes works...
//...
然后我恢复了更改,突然我得到了预期的输出:
registering 1 new size: 1
registering 1 new size: 2
registering classes works...
but reading from main() does not... //it does work this time
checking size directly: 2
checking size through function: 2
checking size on instance: 2
registration from main() uses a different register...
registering 2 new size: 3
registering 3 new size: 4
registering 4 new size: 5
...which is not the one used in the header files
checking size directly: 5
checking size on instance: 5
checking size through function: 5
我一直在研究这个问题,但未能弄清原因。我的猜测是它与编译顺序(但注册如何工作?)或 linkage / storage duration 有关。有人可以解释一下吗?
当你实现自动class注册方案时,你应该注意静态初始化顺序,多线程。
删除 .cpp 文件后它不起作用的原因是头文件未编译,因此没有人知道有任何声明。
我认为您在这里需要的技巧是 ClassRegister
而不是静态数据成员,而是使用具有静态局部变量的函数。这有时被称为单例,虽然我不知道这是否真的是正确的术语。
代码可能如下所示:
typedef std::vector<int> register_type;
register_type& getRegister() {
static register_type registeredClasses; //declaration
return registeredClasses;
}