为啥 C++ 允许通过指针访问枚举?

Posted

技术标签:

【中文标题】为啥 C++ 允许通过指针访问枚举?【英文标题】:Why does C++ allow access to an enum through a pointer?为什么 C++ 允许通过指针访问枚举? 【发布时间】:2013-11-05 17:49:35 【问题描述】:

我正在编写一些代码,其中类中有一个简单的枚举。另一段代码有一个指向该类的指针,并通过箭头指针访问枚举的值。

这个类究竟是如何以这种方式访问​​ MY_VALUE1 的? 我虽然它只允许通过 MyClass::MY_VALUE1 或 MyClass::MyEnum::MY_VALUE1 访问。

class MyClass 
public:
enum MyEnum
    MY_VALUE0 = 0,
    MY_VALUE1 = 1
;
//getters, setters as appropriate
;

//Other class
MyClass* myClass = new MyClass();

//Compiles without C++11
if(getRandomEnum() == myClass->MY_VALUE1)

    //Do Stuff

【问题讨论】:

对于投反对票的人,至少解释一下原因。 我怀疑答案与使用相同机制调用静态类方法时使用的类似语法糖密切相关。这是一个可见性问题,虽然我面前没有标准,但我敢肯定它在某个地方被覆盖。 我手头没有标准,甚至没有 IDE,但我猜嵌入式枚举中的值有点被视为静态 const 成员。 (我相信,如果您可以从空指针成功访问它们,它们静态的) @user1158692 使用空指针执行此操作充其量是实现定义的,按照标准是完全未定义的行为。我记得大约 12 年前在一次 VC++ 开发会议上看到 Don Box 做过一次,懒得扩展 ATL 模板 CComObject<MyClass>::CreateInstance 调用,而是使用 CComObject<MyClass> *p=NULL; p->CreateInstance(&p); 调用它时,他的回答基本上是“它适用于 MS VC++ ,所以请关掉”。 @user1158692 你可以通过空指针访问它,我刚刚用Apple clang 5.0(基于LLVM-3.3 svn)尝试过。 【参考方案1】:

-> 运算符(大部分)是dereference (*) 和selection (.) 的缩写。换句话说,a->b(*(a)).b 相同。 (§5.2.5/2;见下文注释)。

. 语法是类成员访问,由 §5.2.5 [expr.ref] 定义; . 右侧的标识符可以是静态或非静态数据成员、函数或成员枚举器(引用部分的第 4 段)。它不能是嵌套类型。从这个意义上说,成员枚举器在语法上类似于static const 数据成员。

注意事项:

    正如 §13.5.6 所阐明的,a->b 受运算符重载的影响。如果a 不是指针类型,则-> 可能被重载,在这种情况下,表达式被解释为(a.operator->())->b。最终,重载的-> 调用序列必须产生一个指针类型,此时应用§5.2.5/2 的解释。

    Class::membervalue.member 之间的一个重要区别是,在第二种情况下,value 将被评估 即使这对于解析 member 的值是不必要的 .

【讨论】:

感谢您指点标准。我希望我们有一份我可以查看的标准副本。 @Gandalf458:公共草案可从 C++ 标准委员会的页面获得:open-std.org/jtc1/sc22/wg21 这些草案是我们大多数人使用的 :)【参考方案2】:

来自 C++ ISO/IEC 2011

在类范围内声明的枚举器可以使用 类成员访问运算符(::、.(点)和 ->(箭头)),

【讨论】:

重点不是重新设计课程。就是说为什么那个指针可以访问枚举。 也许你应该提到. 符号也应该适用于MyClass 的实例。 感谢您的回复,但我从未收到此伪代码错误。回头看看我添加公众的帖子,以澄清这不是问题所在。我只是想知道为什么指向类的指针可以看到枚举(假设每个角落和缝隙都是公共的)而不是需要范围 :: 运算符。 据我所见,您的原件中没有public...如果您在我阅读时发布它会更好:) 您是想拥有一个单曲吗? ='s 在你的 if 声明中? 我希望我可以选择每个人的答案。他们齐心协力,很好地解释了这个问题。 @Jimbo【参考方案3】:

枚举值被视为静态成员 类,并且可以通过两种方式访问​​:通过类 名称后跟范围解析运算符 (MyClass::MY_VALUE0),或像任何其他成员一样 (instance.MY_VALUE0pointer->MY_VALUE0)。

注意,在后一种情况下,左边的操作数仍然是 评估,即使评估的结果不是 用过的。换句话说,如果我写f()->MY_VALUE0(其中f() 返回一个MyClass*),该函数将被调用,尽管 事实上它的返回值没有被使用。

【讨论】:

以上是关于为啥 C++ 允许通过指针访问枚举?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我可以通过指针访问私有数据成员,我应该这样做吗?

为啥允许将字符串文字分配给 C++ 中 char * 类型的指针 [重复]

为啥 C++ lower_bound() 允许返回与 val 等效的指针,而 upper_bound() 不允许

为啥 c++ 顺序访问迭代器的函数签名不使用指针?

通过指针访问结构中的值? (C++)

为啥C ++允许将指向基对象的指针转换为派生类的指针[重复]