类成员声明的快捷方式

A shortcut for class member declarations

本文关键字:快捷方式 声明 成员      更新时间:2023-10-16

我必须向一个类添加一堆成员。我想添加一个宏

,例如:
#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方法。

我会反驳:如果你只是用简单的getters和setters公开这些成员变量,为什么不让成员变量public并完成它呢?

对这样的编码有什么考虑吗?

是的,所有关于邪恶滥用宏的常见担忧。 让我们来看看与这里相关的一些问题。

你正在创造一种只有你会知道的秘密语言。

如下所示的代码:

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