为什么C++中不存在引用成员?

43

在C++中,我可以选择使用函数指针或函数引用(甚至是函数值,为了完整起见):

void call_function_pointer (void (*function)()) {
    (*function) ();
}
void call_function_reference (void (&function)()) {
    function ();
}
void call_function_value (void function()) {
    function ();
}

然而,当涉及到方法时,我似乎没有指针和引用之间的选择。

template <class T> void call_method_pointer (T* object, void (T::*method)()) {
    (object->*method) ();
}
// the following code creates a compile error
template <class T> void call_method_reference (T& object, void (T::&method)()) {
    object.method ();
}

这使我认为C++中不存在方法引用。 如果是这样,那么它们不存在的原因是什么?

8
你说得对,方法引用并不存在。C++标准没有定义这样的类型,并明确指出(在一篇非规范性说明中),当描述成员指针类型时,“C++中没有“成员引用”类型。”但我无法回答你关于它们不存在的原因的问题。 - user743382
可能是成员函数的引用?的重复。 - Etherealone
1
@Tintin 是的,它确实可以(它们只是指向vtable条目的指针)。这正是指向成员运算符.*->*的用途。问题在于为什么没有成员引用的等效物,即使对象引用和函数引用存在。即使在c.l.c++上,也有多次讨论以至于某人一旦问到“为什么”就会死路一条。我个人非常好奇其中的原理,我相信它被埋藏在某些草案评论中。 - Jason C
1
@Etherealone 出于与使用指针相同的原因,您会使用数据或函数的引用而不是指针。无论是否真正需要引用都是一个不同的争论......但至少根据1989年CFront的原始理由,引用的原始理由是(改编)“将值语义与指针效率相结合”。 OP的问题很有趣:存在对数据、对象、函数和成员的指针。存在对数据、对象和函数的引用——但是不存在对成员的引用,出于纯粹的好奇心,我想知道为什么(加上C++非常明确地省略了它)。 - Jason C
2
(换句话说)问题并不是“你为什么需要这个?”或者“有没有替代方法?”,而是“为什么这些明显缺失?”这是一个学术问题,不一定是一个实际问题。 - Jason C
显示剩余4条评论
1个回答

53
在标准中(例如N3337 - 对于这个来说不是最新的,但足够了),在8.3.3.3节的末尾有一个注释,内容如下:
[注:另请参见5.3和5.5。类型“成员指针”与类型“指针”不同,也就是说,只能通过指向成员的指针声明符语法来声明成员指针,而永远不能通过指针声明符语法来声明成员指针。C++中没有“成员引用”类型。--end note]
当然,也没有“引用成员”类型的运算符(假设最好的我能想到的是像->&.&这样的东西,但这些与数据和函数引用的解除引用不一致,这些不需要特殊的运算符)。
为什么呢?

关于为什么; 经过有趣的历史调查并未找到任何现有记录(我一直追溯到Cfront 2.0,其中pointer-to-member was first supported--编辑:根据更可靠的文件,该功能实际上是在Cfront 1.2中首次支持的),我问了这个人本人,这里是他的回复:

日期:2014年2月22日星期六10:12:51 -0500 发件人:Bjarne Stroustrup <...> 主题:关于缺少成员引用和CFront 2.0
在2014年2月22日6:40 AM,Jason C写道: > 我的问题是:C++非常明确地禁止了“成员引用”的概念。为什么?我一直在做很多研究,我追溯了“指向成员的指针”的起源(我认为)到1989年的CFront 2.0。我阅读了产品参考手册和其他文档,希望能找到一些解释,但没有找到。
我真的不记得了。那是25年前,ARM对此保持沉默。我添加成员指针是为了消除类型系统中的一种罕见的破坏。我怀疑我没有添加成员引用,因为这似乎不值得努力:没有用例。
要说实话,我原本期望的是更加晦涩和复杂的东西。

所以,下一次有人问为什么没有成员引用,你可以自信地说:“因为没有!”(注意:请参见我的评论中的胡言乱语;仍有一些历史调查需要完成才能达到100%的信心。)

个人而言,在我的代码中从未发现过指向成员的指针的用途,但在 Stroustrup 的 The Evolution of C++: 1985-1989 中,给出了它们存在的明确理由,详见第222-223页。


顺便提一下,您调用虚拟成员函数的语法是:
object.method();

...并不是很有意义,因为在语法上无法将其与对名为method()的实际成员的调用区分开来。

如下所示,hvd提出了一个很好的观点:从上面可以看出,在语法上,没有一种一致的方式可以取消引用成员引用。您必须将其与普通成员访问区分开来,但同时您希望使其与对象和函数引用的取消引用保持一致(不需要特殊运算符),我真的想不到任何东西可以同时实现这两个目标。


6
在我看来,你的“顺便说一下”的注释应该是你的答案。单独使用 ->&.& 运算符是没有意义的,引用的一个很大的好处就是你不需要像指针那样解引用它们,而且你最后的注释已经完美地解释了为什么这样做不起作用。 - user743382
1
我的看法是:引用是给定实体的名称。成员的名称不能单独使用(除非隐式使用 this->),因此创建别名将是无用的。 - Potatoswatter
@Potatoswatter:请看更新。似乎“因为它没用”是获胜者! - Jason C
1
Stroustrup在后来的回复中提到:“实际上,贝尔实验室有一份技术备忘录可能会有所启示,但我手头没有。” - 我目前正在寻找并获取这个备忘录,如果我找到了,我会在这里更新。我不知道是否有在线存档,我希望阿尔卡特-朗讯有这些文件并愿意分享。 - Jason C
1
Jason C:我有《C++宝典1&2》,它们提到了以前的论文,也许里面会有。我需要检查一下。 - SJHowe
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接