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

时间:2018-09-19 15:06:04

标签: c++ include static-methods

我想知道在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 */ 
}

1 个答案:

答案 0 :(得分:0)

否,您不能在包含标头(您的问题格式不正确)时调用静态C ++方法,这仅仅是因为#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)将在输入{{1}之前调用BInitializer的构造函数。 }功能。

这是一种骇人听闻的解决方案,但我希望它能达到您的目的。如果您可以避免使用它,建议您不要使用它。