我有一个问题,为什么为什么要“一步一步”编译某个东西,而不能“一步一步”编译却不能编译。我有三节课;
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
声明为const成员函数。
但是常量引用分配给非常量引用
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
是一个常量对象(您在const函数中),因此getTime
的const版本会像以前一样被调用。
const getTime
的返回类型为const Time&
。
然后您进行Time& t =
。这是您的错误所在。 const Time&
无法修改。可以修改Time&
。如果您使用可变引用来引用常量对象,则可以使常量对象发生突变。语言禁止这样做!
要解决此问题,只需使用常量引用:
const Time& t = Travel::getTime();