我有一个问题,为什么某件事可以"一步完成"编译,但不能"两步完成"。我有三节课;
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&'类型的引用会丢弃限定符">?
执行死刑时这两件事不是完全一样吗??
行
Time& t = Travel::getTime();
需要
const Time& t = Travel::getTime();
让它发挥作用。之所以需要这样做,是因为您在一个const限定的函数中。当您在const限定函数中时,类的所有成员都被认为是const
。这意味着当你呼叫getTime
时,你就呼叫
const Time& Travel::getTime() const { return mTimestamp; }
函数的版本。尝试将const Time&
分配给Time&
是行不通的,因为这将剥离返回类型的常量。
在这个函数定义中,您应该删除Analysis::
int Analysis::getUnixTime() const {
Time& t = Travel::getTime();
return t.getTimeAsUnix();
}
称为函数
const Time& Travel::getTime() const { return mTimestamp; }
返回一个常量引用。之所以使用此重载函数,是因为函数getUnixTime
被声明为常量成员函数。
然而,常数参考被分配给非常数参考
Time& t = Travel::getTime();
因此编译器会发出错误。
好的,让我们分解一下工作版本:
int Analysis::getUnixTime() const { // (1)
// (2) --------v v----- (3)
return Travel::getTime().getTimeAsUnix();
}
在(1)
中,函数getUnixTime
被定义为处理常量实例。这意味着您只能调用其他常量函数,不能更改任何成员变量。
在(2)
,调用Travel::getTime()
。此调用非静态成员函数,描述其语法。但没关系,它很清楚,并调用函数的const
版本,返回const Time&
。对常量Time
对象的引用。
在(3)
,成员函数getTimeAsUnix
在const Time&
上被调用。这是完美的,因为Time
有一个以这种方式命名的成员函数,它被标记为处理常量对象。
正如您所看到的,每个对象都是常量,并且您只调用常量函数。
把代码分解成两行时出了什么问题?
让我们来看看你身体里的第一行函数:
Time& t = Travel::getTime();
如前所述,Travel::getTime()
调用非静态成员函数。由于this
是一个常量对象(您在一个常量函数中(,所以getTime
的常量版本会被调用,就像以前一样。
常量getTime
的返回类型为const Time&
。
然后你做Time& t =
。这就是您的错误所在。const Time&
无法修改。可以修改Time&
。如果您使用可变引用引用引用常量对象,那么您就可以对常量对象进行变异。语言禁止!
要解决这个问题,只需使用常量引用:
const Time& t = Travel::getTime();