为什么 '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)
,成员函数 getTimeAsUnix
在 const 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();
我有一个问题,为什么某些东西在完成后可以编译 "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)
,成员函数 getTimeAsUnix
在 const 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();