在C ++中定义私有到公共


Define private to public in C++

本问题已经有最佳答案,请猛点这里访问。

我想定义私有和受保护的公共。

1
2
#define private public
#define protected public

这在C ++中是安全的吗?


不,这几乎肯定会导致未定义的行为。

来自n4296 17.6.4.3.1 [macro.names] / 2 :(来自下面的@james)

A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 2, or to the attribute-tokens described in 7.6.

privatepublic是关键字。如果您在C ++标准库中使用任何内容,那么在其中一个上执行#define是未定义的行为:

17.6.4.1/1 [constraints.overview]

This section describes restrictions on C ++ programs that use the facilities of the C++ standard library.

如果不这样做,17.6.4.3.1中的限制似乎不适用。

另一种可能导致违规的方法是使用具有两种不同定义的相同结构。虽然大多数实现可能并不关心除public vs private之外的两个结构是否相同,但标准并未做出这种保证。

尽管如此,最常见的UB是"它有效",因为很少有编译器在意。

但这并不意味着它"安全"。它在特定的编译器中可能是安全的(检查所述编译器的文档:然而,这将是一个奇怪的保证,但是!)。如果通过两个不同的定义访问相同的结构,很少有编译器(如果有的话)将提供上述所需的布局保证(和修改保证),例如,即使错误的其他可能性更远。

许多编译器都会"正常工作"。这并不能保证安全:下一个编译器版本可以进行无数次更改,并以难以(或简单)检测方式破坏您的代码。

如果收益很大,只做这样的事情。

如果您从不包含任何标准库标头并且不使用它来在两个编译单元中使定义不同,我找不到#define关键字是未定义行为的证据。因此,在高度限制的计划中,它可能是合法的。在实践中,即使它是合法的,它仍然不是"安全的",因为合法性非常脆弱,并且因为编译器不太可能对这种语言滥用进行测试,或者关心它是否会导致错误。

#define private foo引起的未定义行为似乎不限于在std标头的#include之前执行此操作,作为它是多么脆弱的示例。


只允许在不以任何方式(甚至间接)包含标准标题的翻译单元中,但如果您这样做,则存在以下限制:

(17.6.4.3.1) A translation unit shall not #define or #undef names lexically identical to keywords [...]

无论如何,这通常都是一个坏主意 - 使用访问修饰符进行修改对于该词的任何常见含义都不是"安全的",即使它本身不会引起任何直接问题。
如果您正在使用库代码,那么通常有很好的理由来保护它们。

如果您想暂时公开,例如 出于测试目的,您可以为该类的该部分使用特殊的条件宏:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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;
};


这样做没有任何违法行为,它只是疯了。

您必须对所有编译单元使用此定义(否则,由于名称重整,您可能会使链接器失败。

如果你是出于好奇,那么这是完全合法的(如果令人困惑)c ++;如果你问,因为你认为这是一个好主意,所以你没有所有那些讨厌的访问权限,那么你是一个非常糟糕的道路。使用protected和private有一个特定的语义原因,这有助于降低代码的复杂性并解释模块之间的"契约"。使用此定义会使您的代码几乎无法读取实践的c ++程序员。


语法是正确的,但语义是错误的。


访问修饰符仅适用于人类,因此您不会使用您不应访问/更改的方法或字段等。

如果你编写新代码,你总是可以公开一切,但在旧代码中,它肯定会破坏某些东西。它会工作,但它当然也会更容易出错。想象一下,如果您每次都能访问所有内容,IntelliSense会建议什么。访问修饰符不仅可以保护代码,如果以错误的方式使用它可能会破坏某些内容,但它有助于IntelliSense仅向您显示在特定上下文中相关的成员。