Return reference to sliced object (supertype)
-
15-11-2019 - |
Question
Consider the following classes:
class Coord
{
public:
double _x, _y;
Coord(double x, double y)
{
_x = x;
_y = y;
}
};
class NamedPoint : public Coord
{
public:
int _id;
NamedPoint(int id, double x, double y) :
Coord(x,y),
_id(id)
{
}
};
I'd like to create a member function of NamedPoint -- coord() -- that returns a reference of type Coord corresponding to the NamedPoint.
For example, I'd like to something like:
const Coord& NamedPoint::coord()
{
return ((Coord)*this);
}
But I get a warning about temporary variables and I'm not crazy about it.
Of course, the following works:
Coord coord()
{
Coord c = *this;
return c;
}
But I'd rather return a reference.
Does anyone know if this is possible using inherited classes?
Sorry for not explaining the point of the function. I'm overloading the == operator differently for Coord and NamedPoint. Coord would simply check {x,y} and NamedPoint would check {id,x,y}. If I forget to cast a NamedPoint to a Coord before this == test, I'll use the wrong version.
So, while I realize that
(Coord)np1 == (Coord)np2
would give me what I want, I'd rather use something like
np1.coord() == np2.coord()
which I think is more clear as to what is going on.
Solution
What's the point of the function? NamedPoint
is implicitly convertible to Coord
anyway:
void foo(Coord& c)
{
c._x = 5;
}
NamedCoord nc(0, 1, 2);
foo(nc); // c references the Coord part of nc
Anyway, your function should simply use this conversion:
const Coord& NamedPoint::coord()
{
// Bad: takes the value of *this and slices off
// the derived bits, leaving a temporary Coord.
/* return ((Coord)*this); */
// Good: takes the value of *this and refers
// to the base bits, no temporaries.
return *this;
// (Same as:)
/* return ((Coord&)*this); */
}
OTHER TIPS
@GMan gives the main solution.
However, it might be interesting to note in more detail the problem:
const Coord& NamedPoint::coord()
{
return ((Coord)*this);
}
This is much the same as:
const Coord& NamedPoint::coord()
{
Coord c = *this;
return c;
}
Here it is clear that you are returning a reference to a temporary on the stack, which makes the reference to it useless, and hence the warning.
Now in the case presented, Coord
is the base class and hence we have the simple solution given by @Gman.
In the general case, the principle is that if you want a reference to something
, you better make sure that something
will still be around.