2

我将此 C++ 代码视为一个更大示例的一部分:

Date &Date::operator++()
{
    helpIncrement();
    return *this;
}

Date Date::operator++( int )
{
    Date temp = *this;
    helpIncrement();
    return temp;
}

首先如果Date temp = *this,那么我不明白为什么这两个函数的返回类型有什么不同?一个返回*this,另一个返回temp,分配给*this哪个?

其次,为什么第二个函数的参数没有变量名?

4

5 回答 5

6

this第一个返回作为引用指向的对象。也就是说,返回的对象operator++被调用的对象。但是,当您这样做时Date temp = *thistemp是从 的值构造的副本*this。然后将其从函数中复制出来。你从第二个函数得到的是一个全新的对象。对第二个问题的回答中解释了为什么这些功能有这种差异。

增量运算符有两种类型 - 一种是后增量 ( i++),另一种是前增量 ( ++i)。为了能够单独重载它们中的每一个(尽管它们具有相同的名称,operator++),C++ 标准指定后增量运算符采用int具有未指定值的类型的参数。这只是为了让您可以在每次使用运算符时重载函数。由于您不太可能想要使用该未指定的值,因此您不妨将其保留为未命名。

现在,预递增运算符的预期行为是它递增对象并评估为该对象。这就是为什么它在这种情况下返回一个引用。后增量的预期行为是它保留原始值的副本,递增对象,然后返回原始值。因此,它返回temp副本。

于 2012-12-09T21:08:16.717 回答
1

这是一个很好的问题——它突出了 C++ 的设计者采取的一个相当愚蠢的设计选择:

  • 没有参数的重载是预递增的;带有未使用 int参数的重载是后增量。
  • 这就是为什么前增量版本可以返回一个引用,而后增量必须在增加值本身之前复制原始版本。
  • 添加参数的int原因只有一个——区分两个重载;否则它是没有意义的,这就是为什么它的值从未被使用过。
于 2012-12-09T21:07:21.680 回答
1

第一个运算符是预增量的:它增加值并返回结果。第二个是后增量:它增加值,并返回前一个值。在该代码中,temp保存前一个值,helpIncrement()递增该值,然后temp返回前一个值 ( )。参数没有名称的原因是它没有被使用。这有点骇人听闻。编译器知道++my_value应该翻译成my_value.operator++(),并且my_value++应该翻译成my_value.operator++(1). 也就是说,是否存在整数参数决定了调用哪个重载。

于 2012-12-09T21:07:38.140 回答
1
  1. 第一个函数在递增后返回对此的引用。第二个返回这个副本,在它增加之前。

  2. 第二个函数中未使用的参数区分int++ 运算符的前缀(无参数)和后缀(单参数)版本。

这是一个基本主题,请阅读有关重载的内容operator++。你可以从这里开始:运算符重载

于 2012-12-09T21:10:18.377 回答
1

首先如果 Date temp = *this,那么我不明白为什么这两个函数的返回类型有什么不同?

让我们将其与++on good old的情况进行比较int。考虑

int i = 1;
int j = i++;

在此之后,j保留 的旧值i,但i它本身会递增。所以i必须在增量之前被复制,好像++onint被定义为

class int { // pseudocode
  public:
    int operator++(int)
    {
        int temp = *this;
        *this += 1;
        return temp;
    }
};

OTOH,之后

int i = 1;
int j = ++i;

ij具有相同的值,因此++必须已实现为

int &operator()
{
    *this += 1;
    return *this;
}

int从到的更改带来int&了便利:无需制作副本,并且可以++i在需要参考的情况下使用。

其次,为什么第二个函数的参数没有变量名?

因为它永远不应该被使用。该参数是作为句法噱头存在的,因此编译器可以将两种类型的operator++(前增量和后增量)区分开来,但它没有任何明确定义的值。给它一个名字会在编译器中触发一个“未使用的标识符”选项,并启用适当的警告。

于 2012-12-09T21:16:51.023 回答