Возврат ссылки на нарезанный объект (супертип) - PullRequest
1 голос
/ 19 мая 2011

Рассмотрим следующие классы:

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)
    {
    }
};

Я хотел бы создать функцию-член NamedPoint - corre () - которая возвращает ссылку типа Coord, соответствующую NamedPoint.

Например, я хотел бы что-то вроде:

const Coord& NamedPoint::coord()
{
    return ((Coord)*this);
}

Но я получаю предупреждение о временных переменных, и я не без ума от этого.

Конечно,следующие работы:

Coord coord()
{
    Coord c = *this;
    return c;
}

Но я бы предпочел вернуть ссылку.

Кто-нибудь знает, возможно ли это с помощью унаследованных классов?функции.Я по-разному перегружаю оператор == для Coord и NamedPoint.Coord просто проверит {x, y}, а NamedPoint проверит {id, x, y}.Если я забуду привести NamedPoint к Coord до этого теста ==, я буду использовать неправильную версию.

Итак, хотя я понимаю, что

(Coord)np1 == (Coord)np2 

даст мне то, что я хочу, я бы предпочел использовать что-то вроде

np1.coord() == np2.coord()

, которое я считаю более понятнымотносительно того, что происходит.

Ответы [ 2 ]

7 голосов
/ 19 мая 2011

Какой смысл в функции? NamedPoint неявно конвертируется в Coord в любом случае:

void foo(Coord& c)
{
    c._x = 5;
}

NamedCoord nc(0, 1, 2);
foo(nc); // c references the Coord part of nc

В любом случае, ваша функция должна просто использовать это преобразование:

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); */
}
3 голосов
/ 19 мая 2011

@ GMan дает основное решение.

Однако, возможно, было бы интересно отметить более подробно проблему:

const Coord& NamedPoint::coord()
{
    return ((Coord)*this);
}

Это почти так же, как:

const Coord& NamedPoint::coord()
{
    Coord c = *this;
    return c;
}

Здесь ясно, что вы возвращаете ссылку на временный элемент в стеке, что делает ссылку на него бесполезной, и, следовательно, предупреждение.

Теперь в представленном случае Coordявляется базовым классом, и, следовательно, у нас есть простое решение, данное @ Gman.

В общем случае принцип таков: если вам нужна ссылка на something, вам лучше убедиться, что something будетвсе еще рядом.

...