自动注册新的派生类/创建者方法
Automatically register new derived class / creator method
我想如果我给出一个我想要达到的目标的例子会更容易。
假设我想实现一个单元测试环境,在其中实现一个新的单元测试将涉及从给定的基类派生,并且(可能)遵循涉及放置额外宏的指导方针。这样的新测试将自动添加到测试列表中,在某个点上一个接一个地运行。但是有两件事:
-
我试图使创建每个新测试尽可能快速和容易,特别是当涉及到修改文件以外的文件与测试本身。一个完美的情况是,实现一个新测试不需要触及项目中的任何其他文件。这可以通过单例和可能的CRTP来实现,但是现在来看看第2点,
-
目标是具有有限RAM数量的MCU (ROM一般不是问题),我希望能够直接在目标平台上运行测试。因此,在整个应用程序生命周期中占用内存的静态对象是不可接受的。相反,我希望能够仅在需要运行时单独创建和删除每个测试。
基本上,问题归结为一种自动将派生类型(或创建者方法)注册到具有最小RAM开销(我假设会有一些,即至少指向上述方法的指针)的工厂的方法。
很抱歉没有代码示例,但如果没有提交一个给定的实现,这里真的没有什么可展示的。
你能创建一个函数指针的静态/全局向量吗?这些将是指向每个测试类的创建者/工厂函数的指针。工厂函数返回指向基测试类的指针。我本想把它写出来,但我认为代码更容易写和理解。
class TestBase
{
public:
static char registerTest(<function ptr type> creator) {
testCreators.push_back(creator);
return 1;
}
static void runTests()
{
for (auto creator : testCreators)
{
auto newTestClass = creator();
newTestClass->tests();
delete newTestClass;
}
}
private:
void tests() = 0;
std::vector<function ptr type> testCreators;
};
然后是派生类
class SpecificTest : public TestBase
{
// Pretend test code is here.
private:
static char dummy;
};
// Plan old C function. Need to establish naming conventions so as
// not to get multiple symbol errors during linking. Kind of fragile.
TestBase* specificTestCreator()
{
return new SpecificTest();
}
在。cpp文件中为SpecificTest
char SpecificTest::dummy = TestBase::registerTest(specificTestCreator);
我试过编译或运行这个,但我认为它基本上是合理的。
我根据Michael提供的答案创建了一个示例,编译并运行了它。邮编如下
TestBase.h:
#ifndef TESTBASE_H_
#define TESTBASE_H_
#include <vector>
class TestBase {
public:
TestBase();
virtual ~TestBase();
static void RunAllTests();
protected:
virtual void test() = 0;
static char addTestCreator(TestBase* (*creator)());
private:
static std::vector<TestBase* (*)()> &getTests();
};
#endif /* TESTBASE_H_ */
TestBase.cpp
#include "TestBase.h"
TestBase::TestBase() {
}
TestBase::~TestBase() {
}
char TestBase::addTestCreator(TestBase* (*creator)())
{
getTests().push_back(creator);
return 0;
}
void TestBase::RunAllTests()
{
for(std::vector<TestBase* (*)()>::iterator it = getTests().begin(); it != getTests().end(); it++)
{
TestBase *t = (*it)();
t->test();
delete t;
}
}
std::vector<TestBase* (*)()> &TestBase::getTests()
{
static std::vector<TestBase* (*)()> v;
return v;
}
ConcreteTest1.h:
#ifndef CONCRETETEST1_H_
#define CONCRETETEST1_H_
#include "TestBase.h"
class ConcreteTest1: public TestBase {
public:
ConcreteTest1();
virtual ~ConcreteTest1();
protected:
void test();
private:
// both here can be expanded with a macro to make it
// easier as they'll be same for all derived classes
static char dummy;
static TestBase *creator();
};
#endif /* CONCRETETEST1_H_ */
ConcreteTest1.cpp:
#include "ConcreteTest1.h"
#include <iostream>
// can be expanded with a macro
char ConcreteTest1::dummy = TestBase::addTestCreator(ConcreteTest1::creator);
// can be expanded with a macro
TestBase* ConcreteTest1::creator()
{
return new ConcreteTest1();
}
ConcreteTest1::ConcreteTest1()
{
std::cout << "Creating test 1" << std::endl;
}
ConcreteTest1::~ConcreteTest1()
{
std::cout << "Deleting test 1" << std::endl;
}
void ConcreteTest1::test()
{
std::cout << "Running test 1" << std::endl;
}
同样ConcreteTest2.cpp/. h .
从main调用:
TestBase::RunAllTests();
输出是:
Creating test 1
Running test 1
Deleting test 1
Creating test 2
Running test 2
Deleting test 2
这正是我想要达到的。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 自动注册新的派生类/创建者方法