我正在使用 Windows API 在 C++ 中创建自己的 XUL 实现。元素由 XML 解析器构造的事实要求它们具有相同的接口,这样我们就不需要为每个元素构造函数编写自定义代码。结果是我的大部分元素看起来像这样:
class Button : public Element
{
public:
static const char * Type() { return "button"; }
private:
friend class Element;
Button(Element * inParent, const AttributesMapping & inAttributesMapping);
};
class Label : public Element
{
public:
static const char * Type() { return "label"; }
private:
friend class Element;
Label(Element * inParent, const AttributesMapping & inAttributesMapping);
};
class Description : public Element
{
public:
static const char * Type() { return "description"; }
virtual bool init();
private:
friend class Element;
Description(Element * inParent, const AttributesMapping & inAttributesMapping);
};
所以这里有很多代码重复。我想知道用这样的宏调用替换它们是否是个好主意:
#define DECLARE_ELEMENT(ElementType, XULName) \
class ElementType : public Element \
{ \
public: \
static const char * Type() { return XULName; } \
\
private: \
friend class Element; \
ElementType( \
Element * inParent, \
const AttributesMapping & inAttributesMapping); \
}; \
DECLARE_ELEMENT(Window, "window")
DECLARE_ELEMENT(Button, "button")
DECLARE_ELEMENT(Label, "label")
我还没有完全弄清楚这个概念,所以这里缺少一些东西,比如类定义,以及(也许)为每个元素添加方法的能力。
但我想知道您对在这种情况下使用宏的看法。随时分享您的想法。
编辑
我现在正在使用一个小的 ruby 脚本,它从一组模板生成源文件和头文件。我增强了脚本,以便文件也自动标记为在 SVN 上添加,并且修改了 Visual Studio 项目文件以包含这些文件。这为我节省了大量的体力劳动。我对这个解决方案很满意。仅供参考,这就是模板现在的样子:
#ifndef {{ELEMENT_NAME_UPPER}}_H_INCLUDED
#define {{ELEMENT_NAME_UPPER}}_H_INCLUDED
#include "XULWin/Element.h"
namespace XULWin
{
class {{ELEMENT_NAME}} : public Element
{
public:
static ElementPtr Create(Element * inParent, const AttributesMapping & inAttr)
{ return Element::Create<{{ELEMENT_NAME}}>(inParent, inAttr); }
static const char * Type() { return "{{ELEMENT_TYPE}}"; }
virtual bool init();
private:
friend class Element;
{{ELEMENT_NAME}}(Element * inParent, const AttributesMapping & inAttributesMapping);
};
} // namespace XULWin
#endif // {{ELEMENT_NAME_UPPER}}_H_INCLUDED
CPP文件:
#include "XULWin/{{ELEMENT_NAME}}.h"
#include "XULWin/{{ELEMENT_NAME}}Impl.h"
#include "XULWin/AttributeController.h"
#include "XULWin/Decorator.h"
namespace XULWin
{
{{ELEMENT_NAME}}::{{ELEMENT_NAME}}(Element * inParent, const AttributesMapping & inAttributesMapping) :
Element({{ELEMENT_NAME}}::Type(),
inParent,
new {{ELEMENT_NAME}}Impl(inParent->impl(), inAttributesMapping))
{
}
bool {{ELEMENT_NAME}}::init()
{
return Element::init();
}
} // namespace XULWin