为什么在这两种情况下“ const”的行为会有所不同?

时间:2019-10-28 14:13:01

标签: c++ reference const qualifiers

我有一个问题,为什么在“一步完成”时就可以编译某件事,而在“两步完成”时却不能编译。我有三节课;

class Time {
  int mTime;

  int Time::getTimeAsUnix() const {return mTime;}
}

class Travel {
  Time mTimestamp;

  const Time& Travel::getTime() const { return mTimestamp; }
  Time& Travel::getTime() { return mTimestamp; }
}

class Analysis : public Travel {

  int Analysis::getUnixTime() const {
    // Time& t = Travel::getTime();
    // return t.getTimeAsUnix();     // This does NOT compile

    return Travel::getTime().getTimeAsUnix();  // This compiles
  }
}

任何人都知道为什么在Analysis类中编译非注释方法,而注释方法却立即给我“ c ++错误:将'const Time'绑定到类型为'Time&'的引用时会丢弃限定符” 当我尝试吗?

两个人在执行时不是完全一样吗?

3 个答案:

答案 0 :(得分:5)

Time& t = Travel::getTime();

需要成为

const Time& t = Travel::getTime();

使其正常工作。之所以需要这样做,是因为您在const限定的函数内。当您使用const限定的函数时,该类的所有成员都被视为const。这意味着当您致电getTime时,您致电

const Time& Travel::getTime() const { return mTimestamp; }

功能版本。尝试将const Time&分配给Time&是行不通的,因为您将剥夺返回类型的常数。

答案 1 :(得分:4)

在此函数定义中,应删除Analysis::

  int Analysis::getUnixTime() const {
     Time& t = Travel::getTime();
     return t.getTimeAsUnix();  
  }

这里称为函数

const Time& Travel::getTime() const { return mTimestamp; }

返回常量引用。使用此重载函数是因为函数getUnixTime被声明为const成员函数。

但是常量引用分配给了非常量引用

     Time& t = Travel::getTime();

所以编译器会发出错误消息。

答案 2 :(得分:1)

好的,让我们分解一下工作版本:

int Analysis::getUnixTime() const { // (1)
    // (2) --------v        v----- (3)
    return Travel::getTime().getTimeAsUnix();
}

(1),函数getUnixTime被定义为在常量实例上工作。这意味着您只能调用其他常量函数,而不能更改任何成员变量。

(2),调用Travel::getTime()。调用非静态成员函数,尽管语法复杂。但这没关系,很明显并调用了函数的const版本,该版本返回const Time&。对常量Time对象的引用。

(3),成员函数getTimeAsUnixconst Time&上被调用。这是完美的,因为Time有一个成员函数,该成员函数被命名为可以在常量对象上工作的方式。

因此,如您所见,每个对象都是常量,您只调用常量函数。


在两行中分解代码时出了什么问题?

让我们看一下函数主体的第一行:

Time& t = Travel::getTime();

如前所述,Travel::getTime()调用非静态成员函数。由于this是一个常量对象(您在const函数中),因此像以前一样,将调用getTime的const版本。

常量getTime的返回类型为const Time&

然后您执行Time& t =。这是您的错误所在。 const Time&无法修改。可以修改Time&。如果您使用可变引用来引用常量对象,则可以使常量对象发生突变。语言禁止这样做!

要解决此问题,只需使用常量引用:

const Time& t = Travel::getTime();