我正在使用Windows API在C++中创建自己的XUL实现。元素由XML解析器构造的事实要求它们具有相同的接口(interface),因此我们不需要为每个元素构造函数编写自定义代码。结果是我的大多数元素如下所示:
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
最佳答案
我不会在这里使用宏。线索在您的“描述”类中,该类具有一个额外的成员函数init
,其他成员没有。因此,您将无法使用宏来定义它,而是您可以手动扩展该宏并添加多余的行。
对我来说,这比仅写出所有类定义更大地违反了DRY。几乎不重复自己,而只重复一种情况,通常很难维持一致地重复自己。 DRY的目的是找到良好的抽象,而不仅仅是减少样板。
不过,我可以用SetAttributes
类中的Element
函数替换这些构造函数。这可能会减少每个派生类中实际需要的样板数量,因为构造函数是不能从基础继承的一件事。但这取决于每个类的构造函数的实现有多相似。
关于c++ - D.R.Y和 “avoid macros”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1554910/