为什么" #if!(受保护)和!(私人)"无法防御" #define私人公众"?

时间:2015-09-01 01:55:51

标签: c macros

我试着阻止某人像这样强迫私人公开:

#define private public
#if !(protected) and !(private)
#define A 1
#endif
class B{
private:
    int c;
};
int main(){
    int a=A;
    B b;
    b.c=2;
};

一开始我认为这段代码无法编译,因为

#define private public

会触发

#if !(protected) and !(private)

防止A定义。但实际上这段代码可以编译,但同时我可以直接访问B的私有成员,这意味着私有已经公开。但为什么A仍然可以定义?

3 个答案:

答案 0 :(得分:3)

您永远不应#define private之类的关键字。如果您包含来自同一.cpp文件的标准库的任何部分(甚至是<new><initializer_list>等基本语言功能所需的部分),则行为未定义。

也就是说,当#if计算其表达式时,任何标识符或关键字标记都被视为数字零。解释如下:

  1. #if !(protected) and !(private)
  2. #if !(protected) and !(public)
  3. #if !(0) and !(0)
  4. #if true
  5. 您可能正在寻找defined运算符,该运算符会告诉您其操作数是否为宏。

    #if ! defined(protected) and ! defined(private)
    

    但是,不要这样做。

    如果您的目标是阻止某人黑客攻击关键字,可以这样做:

    #if defined(protected) || defined(private) || …
    #   error Do not hack keywords!
    #endif
    

    这对于防御性编码来说太过分了。 C ++并没有真正为您提供防止用户攻击您的库的弹药。不遵守规则的用户会在伤害你之前伤害自己......只需明确表示不支持奇怪的程序。即便如此,也是不必要的,不言而喻。

答案 1 :(得分:0)

该行

typedef struct _charformat2 {
  UINT     cbSize;
  DWORD    dwMask;
  DWORD    dwEffects;
  LONG     yHeight;
  LONG     yOffset;
  COLORREF crTextColor;
  BYTE     bCharSet;
  BYTE     bPitchAndFamily;
  TCHAR    szFaceName[LF_FACESIZE];
  WORD     wWeight;
  SHORT    sSpacing;
  COLORREF crBackColor;
  LCID     lcid;
#if (_RICHEDIT_VER >= 0x0500)
  union {
    DWORD dwReserved;
    DWORD dwCookie;
  };
#else 
  DWORD    dwReserved;
#endif 
  SHORT    sStyle;
  WORD     wKerning;
  BYTE     bUnderlineType;
  BYTE     bAnimation;
  BYTE     bRevAuthor;
#if (_RICHEDIT_VER >= 0x0800)
  BYTE     bUnderlineColor;
#endif 
} CHARFORMAT2;
在预处理阶段评估

。在此阶段,protected和private被视为预处理令牌,而不是关键字。 private已被public替换,因为您已将其定义为public。然后将protected和public的实例替换为0,因为一旦完成所有宏替换,所有剩余的标识符总是被0替换。所以行变为

#if !(protected) and !(private)

大部分细节可以在C99的6.10.1第4段和C ++ 11的16.1第4段中找到。

答案 2 :(得分:0)

privateprotectedpublic部分旨在防止意外滥用。它们不能用于防止故意滥用。

用户更改

是微不足道的
class B{
  private:
    int c;
};

class B{
  public:
    int c;
};

class B{
  private:
    friend class UserClass;
    int c;
};

可以访问B的私人部分。

不要在这些事情上浪费精力。