C++预处理器是如何工作的

How does C++ Preprocessors work?

本文关键字:工作 何工作 预处理 处理器 C++      更新时间:2023-10-16

我目前正在研究开源C++项目,以了解有关C++的更多信息。我正在研究的项目之一位于:

https://github.com/Myzilla-Web-Resources/OpenBlox/

我理解大部分源代码,但我不明白的是他是如何使用预处理器来声明C++类的。

例如,

static_init.h

#define DECLARE_STATIC_INIT(ClassName) 
static void static_init_func(); 
static OpenBlox::static_init_helper ClassName##_static_init_helper
namespace OpenBlox{
class static_init_helper{
    public:
        static_init_helper(init_func_type f){
            static_init::instance().add_init_func(f);
        }
};

实例.h

#define DECLARE_CLASS(Class_Name) 
    virtual Instance* cloneImpl(); 
    virtual QString getClassName(); 
    virtual int wrap_lua(lua_State* L); 
    DECLARE_STATIC_INIT(Class_Name); 
    protected: 
        static QString ClassName; 
        static QString LuaClassName

帧.h

namespace ob_instance{
class Frame: public GuiObject{
    public:
        Frame();
        virtual ~Frame();
        virtual void render();
        DECLARE_CLASS(Frame);
};
}
#endif

请注意,Frame.h继承了Instance.h的所有函数/处理器。有人能向我解释一下这是怎么回事吗?

预处理器只是一个文本查找和替换,因此在您显示的Frame定义中,预处理器首先看到DECLARE_CLASS(Frame),并将其替换为DECLARE_CLASS宏的内容,成为

namespace ob_instance{
class Frame: public GuiObject{
    public:
        Frame();
        virtual ~Frame();
        virtual void render();
        virtual Instance* cloneImpl();
        virtual QString getClassName();
        virtual int wrap_lua(lua_State* L);
        DECLARE_STATIC_INIT(Frame);
    protected:
        static QString ClassName;
        static QString LuaClassName;
};
}

(我清理了格式,实际上整个替换文本都在一行上(。

然后,它备份到插入的文本之前,再次开始通读,并看到DECLARE_STATIC_INIT(Frame)并替换它:

namespace ob_instance{
class Frame: public GuiObject{
    public:
        Frame();
        virtual ~Frame();
        virtual void render();
        virtual Instance* cloneImpl();
        virtual QString getClassName();
        virtual int wrap_lua(lua_State* L);
        static void static_init_func();
        static OpenBlox::static_init_helper Frame_static_init_helper;
    protected:
        static QString ClassName;
        static QString LuaClassName;
};
}

(##是令牌级联运算符(

为您提供最终的Frame类定义。

正如Chris Beck在评论中提到的,您可以使用-E标志来gcc或clang,让编译器输出预处理的文件,而不是编译它。