我想定义私有和受保护的公开。
#define private public
#define protected public
这在C ++中是否安全?
答案 0 :(得分:9)
不,这几乎肯定会导致未定义的行为。
来自n4296 17.6.4.3.1 [macro.names] / 2 :(通过下面的@james)
翻译单位不得
#define
或#undef
在词汇上与关键字,表2中列出的标识符或7.6中描述的属性标记完全相同。
private
和public
是关键字。简单地在其中一个上执行#define
是未定义的行为如果你在C ++标准库中使用了任何东西:
17.6.4.1/1 [constraints.overview]
本节介绍对使用C ++标准库功能的C ++程序的限制。
如果不这样做,17.6.4.3.1中的限制似乎不适用。
它可能导致违规的另一种方式是,如果您使用具有两个不同定义的相同结构。虽然大多数实现可能并不关心除public
与private
之外的两个结构是否相同,但标准并不能保证这一点。
尽管如此,最常见的UB类型是“有效的”,因为很少有编译器在关注。
但这并不意味着它是安全的。它在特定的编译器中可能是安全的(检查所述编译器的文档:然而,这将是一个奇怪的保证,但是!)。如果通过两个不同的定义访问相同的结构,很少有编译器(如果有的话)将提供上述所需的布局保证(和修改保证),例如,即使错误的其他可能性更远。
许多编译器只会“正常工作”。这并不能确保安全:下一个编译器版本可以进行无数次更改,并以难以(或简单)检测方式破坏您的代码。
如果收益很大,只做这样的事情。
如果您从未包含任何标准库标头,并且不使用它来在两个编译单元中使定义不同,我找不到#define
关键字是未定义行为的证据。因此,在高度限制的计划中,它可能是合法的。在实践中,即使它是合法的,它仍然是不安全的,因为合法性非常脆弱,并且因为编译器不太可能对这种语言滥用进行测试,或者关心它是否合法导致一个错误。
由#define private foo
导致的未定义行为似乎并不局限于 #include
std
标题之前的,作为示例如何它很脆弱。
答案 1 :(得分:4)
只允许在翻译单元中以任何方式(甚至间接地)包含标准标题,但如果您这样做,则存在以下限制:
(17.6.4.3.1)翻译单位不得#define或#undef在词汇上与关键词相同[...]
无论如何,这通常都是一个坏主意 - 使用访问修饰符进行捣乱并不是因为该词的任何常见含义而“安全”,即使它本身不会引起任何直接问题。
如果您正在使用库代码,那么通常有很好的理由来保护它们。
如果您想暂时公开,例如出于测试目的,您可以为该类的该部分使用特殊的条件宏:
#if TESTING
#define PRIVATE_TESTABLE public
#else
#define PRIVATE_TESTABLE private
#endif
class Foo
{
public:
Foo();
void operation();
PRIVATE_TESTABLE:
int some_internal_operation();
private:
int some_internal_data;
};
答案 2 :(得分:2)
这样做没有任何违法行为,它只是疯了。
您必须对所有编译单元使用此定义(否则,由于名称重整,您可能会使链接器失败。
如果你是出于好奇,那么这完全合法(如果令人困惑)c ++;如果你问,因为你认为这是一个好主意,所以你没有所有那些讨厌的访问权限,那么你是一个非常糟糕的道路。使用受保护和私有的特定语义原因可以降低代码的复杂性并解释合同的原因。这些模块彼此相关。使用此定义会使您的代码几乎无法读取实践的c ++程序员。
答案 3 :(得分:0)
访问修饰符仅适用于人类,因此您不会使用您不应访问/更改的方法或字段等。
如果你编写新代码,你总是可以公开一切,但在旧代码中,它肯定会破坏某些东西。它会工作,但它当然也会更容易出错。想象一下,如果您每次都能访问所有内容,IntelliSense
会建议什么。访问修饰符不仅可以保护代码,如果以错误的方式使用它可能会破坏某些内容,但它有助于IntelliSense
仅向您显示在特定上下文中相关的成员。
答案 4 :(得分:0)
语法正确但语义错误。