从另一个 header 中的 header 调用静态方法

Call static method from a header inside another header

我想知道在 C++ 中是否有一种方法可以在包含另一个 class 的 header 时从 class 调用静态方法? 我的实现比下面的例子更复杂,但我希望这能更好地解释它:

A.h:

class A
{
public:
    static void myMethod(int a, int b){std::cout << a+b << std::endl;}
    /* other stuff */
}

B.h:

#include "A.h"
class B
{
    /* class definition  */
}
A::myMethod(4,5);

因此在 main 中,当我包含 B.h 时,调用 class A 中的方法:

main.cpp:

#include "B.h"
int main(void)
{
    /* value "4+5" should already be in console output */
    /* do other stuff */
}

非常感谢!

为了避免xy-problem,这里有更详细的解释: 我正在开发一个库,它有一个基础 class 和许多由此派生的 child classes。 这个 child classes 被映射为一个字符串作为键和一个 std::shared_ptr<BaseClass>() 作为值。

现在我的情况是用户应该能够定义自己的 child-classes(如 headers)但不能更改库的源代码。 因此,当用户创建一个新的 .h 文件并将其包含在内时,我试图在包含 child-class header 时直接将新的 child-class 添加到 unordered_map<string, child-class>

A.h:

class A
{
public:
    static bool addNewChild(const std::string name, std::shared_ptr<BaseClass> input_ptr);
    /* other stuff */
private: 
    static std::unordered_map< std::string, std::shared_ptr<BaseClass> > myHashMap;
}
/*initialize pointer with library child-classes */
std::unordered_map< std::string, std::shared_ptr<BaseClass>> A::myHashMap
({
    {child_1, std::make_shared<ChildClass_1>()},
    {child_2, std::make_shared<ChildClass_2>()},
    /*...*/
})

bool A::addNewChild(const std::string name, std::shared_ptr<BaseClass> input_ptr)
{
    /* check if name already in map */
    /* ... */
    /* perform mapping */
    myHashMap[name] = input_ptr
};

B.h:

#include "A.h"
class B
{
    /* class definition  */
}
A::addNewChild("Child_B", std::make_shared<B>());

因此在 main 中,当我包含 B.h 时,调用 class A 中的方法:

main.cpp:

#include "B.h"
int main(void)
{
    /* at this point, child class B should have already be added to myHashMap */ 
}

不,当你包含 header 时你不能调用静态 C++ 方法(你的问题是 ill-formed),因为 #include 语句是由 C 预处理器处理的,在实际的可执行文件被创建。你可以做的是在进入主函数之前强制调用一些静态方法,方法是创建 static const 初始化器:

//  some header with BaseClass
class BaseClass {

};

//  A.hpp
class A
{
public:
    static bool addNewChild(const std::string& name, std::shared_ptr<BaseClass> input_ptr) {
        myHashMap.insert({name, input_ptr});
    }
    static size_t getSize() {
        return myHashMap.size();
    }
    /* other stuff */
private: 
    static std::unordered_map< std::string, std::shared_ptr<BaseClass> > myHashMap;
};

// A.cpp

std::unordered_map< std::string, std::shared_ptr<BaseClass> > A::myHashMap;

//  B.hpp

struct BInitializer {
    BInitializer();
};

class B: public BaseClass
{
private:
    static const BInitializer initializer_;
};

// B.cpp

BInitializer::BInitializer() {
    std::cout << "BInitializer" << std::endl;
    A::addNewChild("Child_B", std::make_shared<B>());
}

const BInitializer B::initializer_ = BInitializer();

// some test written with googletest
TEST(xxx, yyy) {
    std::cout << "main start" << std::endl;
    std::cout << "map size: " << A::getSize() << std::endl;
}

我使用 gtest 框架来演示 BInitializer 构造函数在环境设置之前被调用。可能的输出:

BInitializer
Note: Google Test filter = xxx.yyy
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from xxx
[ RUN      ] xxx.yyy
main start
map size: 1
[       OK ] xxx.yyy (0 ms)
[----------] 1 test from xxx (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[  PASSED  ] 1 test.

如果您这样做,每个链接到 B.cpp 的可执行文件(当然您还需要包含 B.hpp)将在进入 [=] 之前调用 BInitializer 的构造函数18=]函数。

这是一个有点老套的解决方案,但我希望它能为您服务。如果可以避免使用,我建议你不要使用。