c++ - 类成员声明的快捷方式

标签 c++ coding-style

我必须向类(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 定义的 minmax 宏,它破坏了标准库中同名的函数。副作用可能很奇怪,而且如前所述,很难调试。

关于c++ - 类成员声明的快捷方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19455812/

相关文章:

ruby-on-rails - Rails 编码标准 - 为什么要缩进 2 个空格?

c++ - Valgrind 在使用 Boost 线程时报告 'possibly lost' 内存

c++ - C++中析构函数的调用顺序

库之间的 C 字符串转换

java - 在 Java 中避免异常与处理异常

java - i++ 返回 i 而不是 i++

ruby - 条件子句中的赋值是好的 ruby​​ 风格吗?

c++ - 使用 EOF 函数作为条件

c++ - 需要更改 clang 的包含路径

c++ - 没有明确声明的 int[] 中的 foreach