我的系统看起来像这样:
Master.h
extern const Activators[2];
Master.cpp
#include <TypeOne.h>
#include <TypeTwo.h>
const Activators[2] = { &TypeOne::Create, &TypeTwo::Create };
你可以想象TypeOne和TypeTwo是带有静态Create方法的类,它返回一个新实例。
我正在寻找一种方法来分解这个系统,这样就不需要成为一个单独的文件来创建所有类型的链接时依赖。
我希望能够将单元测试与仅仅TypeOne的目标文件和静态Activators数组的版本链接在一起,该数组仅填充了TypeOne创建的函数指针方法。
在C ++中是否有办法创建静态定义的数组,然后在编译单元中填充该数组中的各个插槽?理想情况下,我能够拥有这样的东西:
Master.cpp
const Activators[2];
TypeOne.cpp
Activators[0] = &TypeOne::Create;
TypeTwo.cpp
Activators[1] = &TypeTwo::Create;
答案 0 :(得分:0)
是。虽然你需要非常小心。
TypeOne.cpp
namespace {
class BeforeMain {
BeforeMain() {
Activators[0] = &TypeOne::Create;
}
};
BeforeMain obj;
}
TypeTwo.cpp
namespace {
class BeforeMain {
BeforeMain() {
Activators[1] = &TypeTwo::Create;
}
};
BeforeMain obj;
}
然后,除此之外,在调用main()
之前,不要访问数组。
就个人而言,我希望Activators
成为std::vector<T>
,然后让每个BeforeMain
使用std::vector<T>::push_back()
。
答案 1 :(得分:0)
假设Activators
是一个多态性(Type1
和Type2
都来自Activators
)类型,我会像这样处理问题。
std::vector<std::unique_ptr>>& activators();
std::vector<std::unique_ptr>>& activators()
{
static std::vector<std::unique_ptr>> the_array(2);
return the_array;
}
然后在各个编辑单元中,您可以指定任何您想要的内容:
#include "Activators.h"
struct setup_activator_type_1
{
setup_activator_type_1()
{
activators()[0].reset(new Type1);
}
};
static setup_activator_type_1 type1_static_initializer;
答案 2 :(得分:0)
我会提供一个功能界面来添加Activators
并使用 TypeOne.cpp 和 TypeTwo.cpp 。
在 Activators.h :
void addActivator(Activator activator);
在 Activators.cpp :
中static std::vector<Activator> activators{};
void addActivator(Activator activator)
{
activators.push_back(activator);
}
在 TypeOne.cpp :
struct Initializer
{
Initializer()
{
addActivator(&TypeOne::Create);
}
};
static Initializer initializer;
在 TypeTwo.cpp :
中struct Initializer
{
Initializer()
{
addActivator(&TypeTwo::Create);
}
};
static Initializer initializer;
答案 3 :(得分:0)
C ++初始化全局变量的方式是真的很奇怪,从技术上讲,到目前为止其他答案都有未定义的行为,但无论如何都可能适用于你的机器/编译器。基本上,问题是当程序启动时,实现只需要初始化main.cpp及其标题中的全局变量。当您的代码调用另一个cpp / header组合(翻译单元)中定义的函数时,只有才需要C ++来初始化该一个翻译单元中的全局 。
您的特定情况中最简单(安全)的解决方法是简单地在标头中进行初始化。如果文件包含include "TypeOne.h"
,则会自行初始化Activators[0]
。为了便于携带,包含int main()
的翻译单元(cpp文件)还包括您需要使用的所有这些标题,这一点非常重要。否则,您无法在main
开始之前对其进行初始化。
#include "master.h"
class TypeOne {
static std::unique_ptr<TypeOne> Create();
//stuff
};
static const auto TypeOneInitialized = Activators[0] = &TypeOne::Create;
如果您有一个不应该依赖TypeTwo的cpp,请不要包含它的标题。