为什么 'const' 在这两种情况下表现不同?

Why does 'const' behave differently in these two cases?

我有一个问题,为什么某些东西在完成后可以编译 "in one step" 但在完成后却不能 "in two steps"。我有三个 classes;

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
  }
}

任何人都知道为什么,在分析 class 中,未注释的方法可以编译,而注释的方法在我尝试时立即 "c++ error: binding 'const Time' to reference of type 'Time&' discards qualifiers"

这两个执行起来不就是一回事吗??

Time& t = Travel::getTime();

需要

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

让它工作。需要这样做的原因是因为您在 const 限定的函数中。当您在 const 限定函数中时,class 的所有成员都被视为 const。这意味着当您调用 getTime 时,您调用了

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

函数的版本。尝试将 const Time& 分配给 Time& 是行不通的,因为您会剥夺 return 类型的常量。

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

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

有调用函数

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

即 returns 常量引用。之所以使用这个重载函数,是因为函数getUnixTime声明为const成员函数。

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

     Time& t = Travel::getTime();

所以编译器报错。

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

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

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

(2) 处调用了 Travel::getTime()。这调用了一个 非静态成员函数 ,尽管它有语法。不过没关系,很清楚,调用了const版本的函数,也就是returnconst Time&。对常量 Time 对象的引用。

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

所以如你所见,每个对象都是常量,你只调用常量函数。


将代码分解为两行时出了什么问题?

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

Time& t = Travel::getTime();

正如我们所说,Travel::getTime() 调用了一个 非静态成员函数 。因为 this 是一个常量对象(你在一个 const 函数中),所以 getTime 的 const 版本被调用,就像以前一样。

const getTime 的 return 类型是 const Time&.

然后你Time& t =。这就是你的错误所在。 const Time&无法修改。 A Time& 可以修改。如果您使用可变引用来引用常量对象,那么您将能够改变常量对象。语言禁止这样做!

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

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