Reputation: 274
I have a question about just why a certain thing can be compiled when done "in one step" but can't when done "in two steps". I have three 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
}
}
Anyone knows why, in the Analysis class, the non-commented approach compiles while the commented approach gives me an instant "c++ error: binding 'const Time' to reference of type 'Time&' discards qualifiers" when I try?
Aren't the two the exact same thing when executed??
Upvotes: 0
Views: 135
Reputation: 41750
Okay, let's break down the working version:
int Analysis::getUnixTime() const { // (1)
// (2) --------v v----- (3)
return Travel::getTime().getTimeAsUnix();
}
At (1)
, the function getUnixTime
is defined to work on a constant instance. That means you can only call other constant functions and can't change any member variables.
At (2)
, Travel::getTime()
is called. This call a non-static member function, depite its syntax. But that's okay, it's clear and calls the const
version of the function, which return const Time&
. A reference to a constant Time
object.
At (3)
, the member function getTimeAsUnix
gets called on a const Time&
. This is perfect because Time
has a member function named that way that is marked to work on constant objects.
So as you see, every objects are constant and you only call constant function.
What went wrong when you broke down the code in two lines?
Let's take a look at the first line in the body of you function:
Time& t = Travel::getTime();
As we stated, Travel::getTime()
calls a non-static member function. Since this
is a constant object (you're in a const function) then the const version of getTime
gets called, just as before.
The return type of the const getTime
is const Time&
.
Then you do Time& t =
. This is where you error is. const Time&
cannot be modified. A Time&
can be modified. If you refer to a constant object using a mutable reference, then you'd be able to mutate constant object. The language prohibit that!
To fix this, simply use constant references:
const Time& t = Travel::getTime();
Upvotes: 1
Reputation: 310930
In this function definition where you shall remove Analysis::
int Analysis::getUnixTime() const {
Time& t = Travel::getTime();
return t.getTimeAsUnix();
}
there is called the function
const Time& Travel::getTime() const { return mTimestamp; }
that returns a constant reference. It is this overloaded function is used because the function getUnixTime
declared as a const member function.
However the constant reference is assigned to a non-constant reference
Time& t = Travel::getTime();
so the compiler issues an error.
Upvotes: 4
Reputation: 180414
The line
Time& t = Travel::getTime();
needs to be
const Time& t = Travel::getTime();
for it to work. The reason this is needed is because you are inside a const-qualified function. When you are in a const-qualified function all members of the class are considered to be const
. That means when you call getTime
you call the
const Time& Travel::getTime() const { return mTimestamp; }
version of the function. Trying to assign a const Time&
to a Time&
wont work because you would be stripping away the constness of the return type.
Upvotes: 5