2015-05-05 25 views
3

我发现一段代码如下。何时使用预处理器指令来定义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); 

然后定义这两个函数。

什么时候应该使用预处理器指令?

+3

这不是定义一个函数。 – juanchopanza

+1

当你懒惰时!#¤%&谁不关心可读性。另外:''(void)'' – Biffen

+1

你期望什么答案?随便你怎么做。 – Matt

回答

2

正如@ user258367所说,这个宏可以帮助你用public getter和setter声明私有字段。

如果你有一大堆那些不具备,做低层次的编码为你的IDE,它可以是一个选项,因为:

READWIRTE(int, mSessionId, SessionId) 

比完整的代码更简洁。

但是,除非它是在企业环境中一个常见的用法,并列入在许多项目中共享的.h,我不会使用它:

  • 写第一个领域,以及后来的getter和setter似乎更常见的用法
  • 鼓励总是有getter和setter,甚至一人useles(但你可能有其他的宏只读,只写)
  • 它让你在隐含能见度public:这可能会造成混淆

    private: 
        int foo; // private, no need for getter or setter 
        READWIRTE(int, mSessionId, SessionId); 
        double bar; // is public ! 
    
    public: 
        void othermethod(); 
        ... 
    
1

看来这是一个用于在类上生成“属性”的宏。作者很可能使用它作为快捷方式,而不是手工输入私有成员/访问器/增变器。

2

这个宏将确保每个变量都能正确定义它的setter和getter。

这将有助于您的开发人员认为每次写变量,getter和setter都浪费时间的情况。他可以简单地称这个宏。如果你想要setter和getter,那么对于做代码检查的人来说,这将更容易,因为他/她将知道会发生什么(在这种情况下它将是宏观的)。

1

我看到了两个很好的理由使用宏:

  • 喜欢这里,作为简写,以避免繁琐的输入;

  • 确保在不同平台或代码的不同变体之间的代码的可移植性,当您不想将非可移植构造函数(函数调用)包含在额外函数中时。

1

请不要这样做。

它完成的原因是它可以节省您一些打字的时间。巨大的缺点是它会严重干扰调试。假设您在代码中可能包含错误的区域中看到对setSessionId的调用。您搜索setSessionId的定义。而你找不到它。源代码中的任何位置都没有该方法的定义。工具可能不够聪明,无法指向READ_WIRTE宏。所以那时你完全被卡住了。与其花费5秒寻找方法定义,并且看到它只设置一个成员变量并且可能无害,而是花费年龄寻找函数的定义。

(有些人可能会争辩说,你应该期望setSessionId只是设置一个成员变量,当你的代码存在错误时不是这样,你知道不符合你的期望)。

1

该代码看起来旨在为用户提供简单的向类中添加属性的简写。乍一看,它似乎是一个有用的快捷方式来防止不必要的输入。然而,简单地在成员函数中添加getter和setter可能并不总是最好的路线,原因如下。

  1. 在这种情况下,几乎没有任何价值被添加到简单添加公共成员变量,因为函数只是设置或返回值。
  2. 这两个函数中的其中一个可能不是必需的。例如,如果使用RAII,则该值设置为对象构造,添加一个设置器可能不是必需的,或者实际上是不合需要的。
  3. 它可能完全不支持大对象或以有效的方式支持大对象。
  4. 它不会(目前的形式)是线程安全的。
  5. 除非使用此代码也生成或使用类似的宏,在某些时候这些函数调用将被客户端代码调用,因此getters和setters必须手动编码(即使他们不会不会严格地出现在头文件中)并且...
  6. ...在通过源代码查找定义时,调试将会更加困难,例如,setSessionId()它不会在任何地方找到。

尽管可以使用宏实现此操作,但使用宏的normal warnings也适用。结论是在走这条路线之前要三思。