我必须在课堂上添加一堆成员。我想添加一个像这样的宏:
#define MEMBER(TYPE,NAME) \
private: TYPE m_##NAME; \
public: TYPE get##NAME() const { return m_##NAME; } \
public: void set##NAME(TYPE in##NAME) { m_##NAME = in##NAME; }
然后使用它将成员添加到类中:
class foo {
MEMBER(std::string, OutputDir);
MEMBER(int, MaxIterations);
MEMBER(double, OptimizationCutoff);
// And a couple dozen more members...
public:
// The rest of the class declarations
};
意图显然是要快捷方式的多个代码实例,每个类成员中有3行:
private: std::string m_OutputDir;
public: std::string getOutputDir() const { return m_OutputDir; }
public: void setOutputDir(std::string inOutputDir) { m_OutputDir = inOutputDir; }
对这样的编码是否有任何考虑?
答案 0 :(得分:4)
首先,我要指出一个观察结果。您在此处定义的宏似乎 完全无用 。我得到你想要做的 - 用一行代码声明一个成员变量和简单的getter和setter方法。
我会反驳:如果你只是用简单的getter& amp;暴露这些成员变量。 setters,为什么不只是使成员变量public
并完成它?
对这样的编码是否有任何考虑?
是的,关于Evil滥用宏的所有常见问题。让我们来看看这里的一些内容。
代码如下:
class foo {
MEMBER(std::string, OutputDir);
MEMBER(int, MaxIterations);
MEMBER(double, OptimizationCutoff);
// And a couple dozen more members...
public:
// The rest of the class declarations
};
在它的构造中,一目了然可能有点,但是当需要维护或扩展其中一个成员foo
时,有许多细节被模糊不清,或者宏本身。
例如,只是看了一遍,我就明白你要声明一个成员OutputDir
,但实际上并没有迹象表明它是数据成员还是成员函数。如果它是成员函数,返回类型是什么?有什么参数?我如何声明成员函数模板?什么是模板参数?
你已经在这里构建了一个语法,可以在第一次键入代码时保存一两次击键,但是当有人需要回答任何这些问题时,可能会产生数小时的挫败感和头脑冲击。由于除了您之外没有任何人记录或支持,您的宏最终会类似于只有您知道的秘密语言。
对使用宏的代码进行标记时,您会看到替换文本 - 而不是宏或调用它的方式。这可能非常令人困惑。
宏是一种强制文本替换工具。它们不尊重任何名称空间或范围,并且在定义和调用它们的任何地方都被普遍应用。这完全围绕C ++类型系统,并允许您编写代码,否则会引起错误。
一个常见的例子是VisualStudio对min
和max
宏的定义,它在标准库中以相同的名称破坏了这些函数。副作用可能很奇怪,如上所述,很难调试。