何时使用预处理器指令在 C++ 中定义函数?
When to use preprocessor directives to define functions in C++?
找到一段代码如下
#define READWRITE READWIRTE
#define READWIRTE(varType, varName, funName) \
private: varType varName; \
public: varType get##funName(void) const { return varName; }\
public: void set##funName(varType var){ varName = var; }
READWIRTE(int, mSessionId, SessionId)
我想知道为什么不以正常形式定义函数。我的意思是,像这样:
private:
int mSessionId;
public:
public int getSessionId() const;
public void setSessionId(int sessionId);
然后定义这两个函数
什么时候应该使用预处理器指令?
看来这是在类上生成"properties"的宏。作者很可能将其用作快捷方式,而不是手动输入私有 member/accessor/mutator。
此宏将确保您已正确定义每个变量的 setter 和 getter。
如果您的开发人员认为每次编写变量 getter 和 setter 都是浪费时间,这将有所帮助。他可以简单地调用这个宏。这对于进行代码审查的人来说会更容易,因为如果你想要 setter 和 getters.
,he/she 会知道会发生什么(在这种情况下它将是宏)
我看到使用宏的两个很好的理由:
喜欢这里,作为shorthand避免繁琐的打字;
当您不想在额外函数中包装不可移植的构造(函数调用)时,确保代码在不同平台或不同代码变体之间的可移植性。
如@user258367 所述,此宏可帮助您使用 public getter 和 setter.
声明私有字段
如果你有一大堆这样的东西,但没有 IDE 为你做低级编码,它可以是一个选择,因为 :
READWIRTE(int, mSessionId, SessionId)
比完整代码更简洁。
但除非它在公司环境中很常见,并且包含在 .h
多个项目共享的项目中,否则我不会使用它:
- 先写字段,然后再写 getters 和 setters 似乎更常见
- 它鼓励总是有 getter 和 setter 即使一个是有用的(但你可能有其他宏用于 READONLY 和 WRITEONLY)
它隐含地让你处于 public:
可见性中,这可能会造成混淆
private:
int foo; // private, no need for getter or setter
READWIRTE(int, mSessionId, SessionId);
double bar; // is public !
public:
void othermethod();
...
请不要这样做。
之所以这样做,是因为它可以让您少打一些字。巨大的缺点是它严重干扰调试。假设您在可能包含错误的代码区域中看到对 setSessionId 的调用。您搜索 setSessionId 的定义。你找不到它。您的源代码中的任何地方都没有该方法的定义。工具可能不够智能,无法将您指向 READ_WIRTE 宏。所以那时你完全被困住了。与其花五秒钟寻找方法定义并看到它只是设置了一个成员变量并且可能是无害的,不如花很长时间寻找函数的定义。
(有些人可能会争辩说,您应该期望 setSessionId 只是设置一个成员变量。当您的代码中存在错误时,情况并非如此。您知道 something 不会做你期望它做什么)。
该代码看起来旨在为用户提供 shorthand,以便非常简单地将 属性 添加到 class。乍一看,它似乎是一个有用的快捷方式,可以防止不必要的输入。但是,由于以下原因,简单地在成员函数周围添加 getter 和 setter 可能并不总是最好的前进路线。
- 在这种情况下,与简单地添加 public 成员变量相比,几乎没有添加任何值,因为函数只是设置或 return 值。
- 这两个功能中的一个很可能不需要。例如,如果使用 RAII,该值设置为 object 构造,添加 setter 可能不需要或实际上是不需要的。
- 它可能根本不支持大的 objects,或者以有效的方式支持。
- 它不会(以目前的形式)thread-safe。
- 除非使用它的代码也生成或使用类似的宏,否则在某些时候这些函数调用将由客户端代码调用,因此 getters 和 setters 将必须在那里手工编码(即使它们没有严格出现在 headers 中)和 ...
- ...在查看源代码的定义时调试会更加困难,例如
setSessionId()
它不会在任何地方找到。
虽然可以使用宏来实现此目的,但适用有关使用宏的 normal warnings。结论是在走这条路之前要三思。
找到一段代码如下
#define READWRITE READWIRTE
#define READWIRTE(varType, varName, funName) \
private: varType varName; \
public: varType get##funName(void) const { return varName; }\
public: void set##funName(varType var){ varName = var; }
READWIRTE(int, mSessionId, SessionId)
我想知道为什么不以正常形式定义函数。我的意思是,像这样:
private:
int mSessionId;
public:
public int getSessionId() const;
public void setSessionId(int sessionId);
然后定义这两个函数
什么时候应该使用预处理器指令?
看来这是在类上生成"properties"的宏。作者很可能将其用作快捷方式,而不是手动输入私有 member/accessor/mutator。
此宏将确保您已正确定义每个变量的 setter 和 getter。
如果您的开发人员认为每次编写变量 getter 和 setter 都是浪费时间,这将有所帮助。他可以简单地调用这个宏。这对于进行代码审查的人来说会更容易,因为如果你想要 setter 和 getters.
,he/she 会知道会发生什么(在这种情况下它将是宏)我看到使用宏的两个很好的理由:
喜欢这里,作为shorthand避免繁琐的打字;
当您不想在额外函数中包装不可移植的构造(函数调用)时,确保代码在不同平台或不同代码变体之间的可移植性。
如@user258367 所述,此宏可帮助您使用 public getter 和 setter.
声明私有字段如果你有一大堆这样的东西,但没有 IDE 为你做低级编码,它可以是一个选择,因为 :
READWIRTE(int, mSessionId, SessionId)
比完整代码更简洁。
但除非它在公司环境中很常见,并且包含在 .h
多个项目共享的项目中,否则我不会使用它:
- 先写字段,然后再写 getters 和 setters 似乎更常见
- 它鼓励总是有 getter 和 setter 即使一个是有用的(但你可能有其他宏用于 READONLY 和 WRITEONLY)
它隐含地让你处于
public:
可见性中,这可能会造成混淆private: int foo; // private, no need for getter or setter READWIRTE(int, mSessionId, SessionId); double bar; // is public ! public: void othermethod(); ...
请不要这样做。
之所以这样做,是因为它可以让您少打一些字。巨大的缺点是它严重干扰调试。假设您在可能包含错误的代码区域中看到对 setSessionId 的调用。您搜索 setSessionId 的定义。你找不到它。您的源代码中的任何地方都没有该方法的定义。工具可能不够智能,无法将您指向 READ_WIRTE 宏。所以那时你完全被困住了。与其花五秒钟寻找方法定义并看到它只是设置了一个成员变量并且可能是无害的,不如花很长时间寻找函数的定义。
(有些人可能会争辩说,您应该期望 setSessionId 只是设置一个成员变量。当您的代码中存在错误时,情况并非如此。您知道 something 不会做你期望它做什么)。
该代码看起来旨在为用户提供 shorthand,以便非常简单地将 属性 添加到 class。乍一看,它似乎是一个有用的快捷方式,可以防止不必要的输入。但是,由于以下原因,简单地在成员函数周围添加 getter 和 setter 可能并不总是最好的前进路线。
- 在这种情况下,与简单地添加 public 成员变量相比,几乎没有添加任何值,因为函数只是设置或 return 值。
- 这两个功能中的一个很可能不需要。例如,如果使用 RAII,该值设置为 object 构造,添加 setter 可能不需要或实际上是不需要的。
- 它可能根本不支持大的 objects,或者以有效的方式支持。
- 它不会(以目前的形式)thread-safe。
- 除非使用它的代码也生成或使用类似的宏,否则在某些时候这些函数调用将由客户端代码调用,因此 getters 和 setters 将必须在那里手工编码(即使它们没有严格出现在 headers 中)和 ...
- ...在查看源代码的定义时调试会更加困难,例如
setSessionId()
它不会在任何地方找到。
虽然可以使用宏来实现此目的,但适用有关使用宏的 normal warnings。结论是在走这条路之前要三思。