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

Call static method from a header inside another header

本文关键字:调用 静态方法 另一个      更新时间:2023-10-16

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

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时,类A中的方法被称为:

main.cpp

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

提前非常感谢!

为了避免xy问题,这里有一个更详细的解释: 我正在开发一个库,它有一个基类和许多由此派生的子类。 此子类使用字符串作为键,将std::shared_ptr<BaseClass>()作为值进行映射。

现在我遇到的情况是,用户应该能够定义自己的子类(作为标头(,但不能更改库的源代码。 因此,当用户创建一个新的 .h 文件并包含它时,我尝试在包含子类标头时直接将新的子类添加到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时,类A中的方法被称为:

main.cpp

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

不,当您包含标头时,您不能调用静态C++方法(您的问题格式不正确(,这仅仅是因为#include语句是在创建实际可执行文件之前由 C 预处理器处理的。你可以做的是通过创建static const初始值设定项在进入 main 函数之前强制调用一些静态方法:

//  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(将在进入main函数之前调用BInitializer的构造函数。

这是一种黑客解决方案,但我希望它能满足您的目的。如果你能避免使用它,我建议你不要使用它。