我有一个问题,为什么在“一步完成”时就可以编译某件事,而在“两步完成”时却不能编译。我有三节课;
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&'的引用时会丢弃限定符” 当我尝试吗?
两个人在执行时不是完全一样吗?
答案 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)
,成员函数getTimeAsUnix
在const 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();