Оператор перегрузки *, чтобы получить ссылку на экземпляр другого класса - PullRequest
0 голосов
/ 06 октября 2018

У меня есть классы

class Square
{
public:
    virtual void apply(Player*) = 0; //apply square effect to the player
};

class BoardIterator
{
public:
    BoardIterator();
    Square &operator*();//return current square where player is
    Square &operator+(int);//move forward certain number of squares
private:
    static const int pathLength = 8;//length of outer path
    static const int innerPathLength = 4;//length of inner path
    int curPosition;//number of current square
    Square *outerPath[pathLength];
    Square *innerPath[innerPathLength];
};

class UpdateStatusSquare : public Board::Square
{
public:
    void apply(Player*);
};

/*
Square where player can choose career path
*/
class CareerSquaere : public Board::Square
{ 
public:
    void apply(Player*);
};

* boardIterator должен вернуть ссылку на объект Square.Это моя реализация этого оператора

Board::Square& Board::BoardIterator::operator*()
{
     return *(outerPath[curPosition]);
}

Я пытаюсь проверить это таким образом

Board::BoardIterator iter;
UpdateStatusSquare x = *iter;

Но у меня

Ошибка C2440 'инициализация': невозможно преобразовать 'Board :: Square' в 'UpdateStatusSquare' CareersGame

Как правильно реализовать эту перегрузку?

1 Ответ

0 голосов
/ 06 октября 2018

В чем проблема?

Сообщение об ошибке другого компилятора может пролить свет на проблему:

ошибка: преобразование из «квадрата» в нескалярный тип «UpdateStatusSquare»'запрашивается

Вы определили operator*() вашего BoardIterator для возврата ссылки на Square, а не UpdateStatusSquare.И на самом деле это работает очень хорошо, если использовать его по назначению:

BoardIterator iter;
Square& x = *iter;   // no compiler issue ! I could use x later on 

Ваше первоначальное назначение вызывает проблему, поскольку компилятор не знает, как преобразовать Square в UpdateStatusSquare.Как мог компилятор сделать это, если возвращаемый вами квадрат будет CareerSquaere?

Как ее решить?

Вы должны обращаться с абстрактными полиморфными классами с осторожностью.Во-первых, если вы делаете присваивание значения, как вы пытались, вы можете slice возвращаемый объект.Так что лучше всего использовать ссылки, указатели (или, лучше, умные указатели).

Теперь преобразование Square (не зная, какой именно это тип квадрата) в UpdateStatusSquare называется downcasting .Вы можете сделать это, но с особой осторожностью, используя dynamic_cast:

UpdateStatusSquare *it = dynamic_cast<UpdateStatusSquare*>(&*iter);
if (it) {
    // conversion worked the iterator pointed to a compatible type
}
else {
    // it==nullptr because iterator pointed to an incompatible kind of square
}

Демо

...