开发者

Return reference to sliced object (supertype)

开发者 https://www.devze.com 2023-03-06 17:51 出处:网络
Consider the following classes: class Coord { public: double _x, _y; Coord(double x, double y) { _x = x; _y = y;

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 w开发者_如何学Could 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.


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); */
}


@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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号