从另一个 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=]函数。
这是一个有点老套的解决方案,但我希望它能为您服务。如果可以避免使用,我建议你不要使用。
我想知道在 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=]函数。
这是一个有点老套的解决方案,但我希望它能为您服务。如果可以避免使用,我建议你不要使用。