我必须向类(class)中添加一群成员。我想添加一个这样的宏:
#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; }
是否有任何考虑反对这样的编码?
最佳答案
首先,我要指出一个观察结果。您在此处定义的宏似乎完全没用。我明白你想做什么——用一行代码声明一个成员变量和简单的 getter 和 setter 方法。
我会反驳:如果您只是使用简单的 getter 和 setter 公开这些成员变量,为什么不直接将成员变量设为 public
并完成它呢?
Are there any consideration against coding like that?
是的,所有关于 Evil 滥用宏的常见问题。让我们通过一些与此处相关的内容。
你正在创造一种只有你自己知道的 secret 语言。
代码如下:
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
,但实际上没有任何迹象表明它是数据成员还是成员函数。如果是成员函数,返回类型是什么?参数是什么?我将如何声明成员函数模板?模板参数是什么?
您在这里构建的语法可能会在第一次输入代码时节省一两次击键,但当有人需要回答这些问题时,可能会产生数小时的挫败感和头痛。由于除您之外没有任何人记录或支持它,因此您的宏最终类似于一种只有您知道的 secret 语言。
宏很难调试
当调试使用宏的代码时,您会看到替换的文本——而不是宏或宏的调用方式。这可能会让人非常困惑。
宏没有命名空间
宏是一种强力文本替换工具。它们不尊重任何 namespace 或范围,并且普遍适用于定义和调用它们的任何地方。这完全绕过 C++ 类型系统,让您编写的代码不会引发错误。
宏有奇怪的和意想不到的副作用,并被应用在你没有预料到的地方。
一个常见的例子是 VisualStudio 定义的 min
和 max
宏,它破坏了标准库中同名的函数。副作用可能很奇怪,而且如前所述,很难调试。
关于c++ - 类成员声明的快捷方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19455812/