通过基础class中的方法触发派生class的添加方法

Trigger added methods of derived class by method in base class

我想实现一个简单的测试结构。下面是我如何创建基础 class 和派生 class.

testBase.h:

class TestBase {
public:
    TestBase() {}
    virtual void TestStart() = 0;
    virtual void TestEnd() = 0;
    void RunTest() {  
        // I need code here to trigger a chain of calls
    }
};

classifierTest.h:

#include "testBase.h"

class ClassifierTest: public TestBase
{
public:
    ClassifierTest() {
    
    }
    void TestStart();
    void TestEnd();

    void Test1();
    void Test2();
    void Test3();
};

classifierTest.cpp:

#include "classifierTest.h"

void ClassifierTest::TestStart() {

}

void ClassifierTest::TestEnd() {

}

void ClassifierTest::Test1(){

}

void ClassifierTest::Test2(){

}

void ClassifierTest::Test3(){

}

主要功能:

ClassifierTest *classifierTest = new ClassifierTest();
classifierTest->RunTest();

假设Test1()Test2()Test3()是我的测试方法,以后我可能会在这里添加更多测试。 我的目标是当我在main函数中调用RunTest()的时候,然后这些测试方法一个一个调用,在TestStart()之后,TestEnd().

之前

所以他们会 运行 喜欢:

我不想在基础中专门添加测试方法class。但问题是如何从 RunTest() 触发这些调用链。所以它不知道它们的基本触发方法。

我认为它应该像 .net 中的反射一样?

您基本上是在要求 C++ 中不存在的反射(目前)。现在的问题是你愿意做出什么样的妥协

如果您愿意编写一些代码来手动注册测试函数,那么他们就不需要成为成员,一个可能的解决方案是:

#include <functional>
#include <vector>
#include <iostream>
class TestBase {
public:
    TestBase() {}
    virtual void TestStart() = 0;
    virtual void TestEnd() = 0;
    
    void RunTest() {  
        for (const auto& test_fun : test_functions){
            TestStart();
            test_fun();
            TestEnd();
        }
    }
    using test_function = std::function<void()>;
    void register_test(const test_function& fun){ test_functions.push_back(fun); }
private:
    
    std::vector<test_function> test_functions;
};

class ClassifierTest: public TestBase
{
public:
    ClassifierTest() {
        register_test([](){ std::cout << "test 1\n";});
        register_test([](){ std::cout << "test 2\n";});
    }
    void TestStart() { std::cout << "test start\n";}
    void TestEnd() { std::cout << "test end\n";}
};

int main() {
    ClassifierTest{}.RunTest();
}

Output:

test start
test 1
test end
test start
test 2
test end

请注意,如果您捕获 this lambda 可以使用成员,因此与您的初始方法没有太大区别,并且要编写的代码量也相当:

class ClassifierTest2: public TestBase
{
public:
    ClassifierTest2() {
        register_test([this](){ std::cout << "test 1, x = " << x << "\n";});
        register_test([this](){ std::cout << "test 2, x = " << x << "\n";});
    }
    void TestStart() { ++x;std::cout << "test start\n";}
    void TestEnd() { std::cout << "test end\n";}
private:
    int x = 0;
};

int main() {
    ClassifierTest2{}.RunTest();
}

Output:

test start
test 1, x = 1
test end
test start
test 2, x = 2
test end

如评论中所述,如果您也手动注册 TestStartTestEnd,则不需要派生的 classes。它可以只是 class Testregister_test_start(std::function<void()>)register_test_end(std::function<void()>) 或将它们作为参数传递给构造函数。