【问题标题】:Why can't you overload the '.' operator in C++?为什么你不能超载'。' C++ 中的运算符?
【发布时间】:2010-10-05 22:09:46
【问题描述】:

能够重载 . C++ 中的运算符并返回对对象的引用。

您可以重载operator->operator*,但不能重载operator.

这有技术原因吗?

【问题讨论】:

  • 你能举个例子说明你什么时候想覆盖'。'运营商?
  • 一般情况下,用例是“智能引用”。一种代理。
  • @Gamecat:阅读this 提案以添加重载operator.operator.* 的能力,它有几个例子。
  • @ToonKrijthe . 周围的空格是允许的,所以也许有一些聪明但令人震惊的动态调度黑客允许将点积表示为 matrix1 . matrix2

标签: c++ operator-overloading


【解决方案1】:

this quote from Bjarne Stroustrup:

运算符。 (dot) 原则上可以使用相同的方法重载 用于 -> 的技术。但是,这样做可能会导致问题 关于一个操作是否意味着对象重载。或一个 引用的对象。例如:

class Y {
public:
    void f();
    // ...
};

class X {    // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};

void g(X& x)
{
    x.f();    // X::f or Y::f or error?
}

这个问题可以通过多种方式解决。在那个时间 标准化,尚不清楚哪种方式最好。更多 详情见The Design and Evolution of C++

【讨论】:

  • TDaEoC++ 在我的回答中的完整引用。
  • 我很想否决这个抄袭/重新着色。引用时,逐字引用,不要调整。并使用报价格式。
  • 这个例子只是重载解析的歧义,指出需要更仔细的编程(参见:stackoverflow.com/questions/13554606/…)这种情况不应成为不重载的理由operator .
  • @slashmais 否。operator. 的理由与operator-> 明确平行。你怎么能做重载决议?
  • 请注意,后来,Bjarne Stroustrup 支持 operator dot,甚至为此提出了一项提案,但显然(尚未)接受:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4477.pdf - 正如@emlai 已经添加的那样作为对问题的评论
【解决方案2】:

Stroustrup 说 C++ 应该是一种可扩展但不可变的语言。

点(属性访问)运算符被认为过于接近语言的核心,不允许重载。

参见The Design and Evolution of C++,第 242 页,11.5.2 智能引用部分

当我决定允许运算符->重载时,我自然会考虑运算符.是否可以类似地重载。

当时,我认为以下论点是决定性的:如果obj 是一个类对象,那么obj.m 对该对象类的每个成员m 都有意义。我们尽量不通过重新定义内置操作来使语言可变(尽管出于迫切需要,= 和一元 & 违反了该规则)。

如果我们允许类X 重载.,我们将无法通过正常方式访问X 的成员;我们将不得不使用指针和->,但->& 也可能已被重新定义。我想要一种可扩展的语言,而不是可变的。

这些论点很有分量,但不是结论性的。特别是,在 1990 年,Jim Adcock 提议允许运算符 . 的重载完全运算符 -> 的方式。

这句话中的“我”是 Bjarne Stroustrup。没有比这更权威的了。

如果你想真正了解 C++(如“为什么会这样”),你绝对应该阅读这本书。

【讨论】:

    【解决方案3】:

    斯特鲁普has an answer for this question:

    运算符。 (点)原则上可以是 使用相同的技术重载 用于->。但是,这样做可以 引发关于是否 操作是针对对象的 超载。或引用的对象 经过 。例如:

    class Y {
    public:
        void f();
        // ...
    };
    class X {   // assume that you can overload .
        Y* p;
        Y& operator.() { return *p; }
        void f();
        // ...
    };
    void g(X& x)
    {
        x.f();  // X::f or Y::f or error?
    }
    

    这个问题可以分几个解决 方法。在标准化的时候, 哪条路是不明显的 最好的。详情请见D&E

    【讨论】:

    • 查看我对安东回答的评论
    【解决方案4】:

    很容易理解,如果通过算子函数调用的内部机制, 假设一个类复合体可以有两个成员 r 代表实部,i 代表虚部。 Say Complex C1(10,20),C2(10,2) // 我们假设类中已经有一个两个参数的构造函数。 现在,如果您将 C1+C2 写为语句,那么编译器会尝试在复数上查找 + 运算符的重载版本。现在我们假设我重载了 + 运算符,所以 C1+C2 内部翻译为 c1.operator+(c2) 现在暂时假设你可以超载'。操作员。 所以现在想想下面的调用 C1.disp()//显示复杂对象的内容 现在尝试表示为内部表示 C1.operator.(------) ,创建了完全混乱的东西。这就是我们不能超载'.'的原因。运营商

    【讨论】:

    猜你喜欢
    • 2015-11-13
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 2021-07-02
    • 1970-01-01
    相关资源
    最近更新 更多