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

use*_*862 5 c++

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

#define private public
#define protected public
Run Code Online (Sandbox Code Playgroud)

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

Yak*_*ont 9

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

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

翻译单元不得#define或在#undef词汇上与关键词,表2中列出的标识符或7.6中描述的属性标记相同.

private并且public是关键字.如果你在C++标准库中使用任何东西,那么简单地#define在其中一个上做一个未定义的行为:

17.6.4.1/1 [constraints.overview]

本节介绍对使用C++标准库功能的C++程序的限制.

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

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

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

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

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

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

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

引起未定义行为#define private foo似乎并没有被限制在这样做之前#include的的std头,因为它是多么脆弱的一个例子.

  • @DanielSanchez可能不是UB本身(虽然我必须检查)但UB如果影响和标准库头.至于"这不可能是UB ......",如果标准说它是,那就是. (3认同)

mol*_*ilo 6

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

(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;
};
Run Code Online (Sandbox Code Playgroud)

  • `friend class Test_Foo;` 我认为会更好。 (2认同)