отменить повтор с помощью механизма автоматического удаления - PullRequest
0 голосов
/ 09 декабря 2008

Мое приложение разработано на C ++ с использованием Qt и использует сигналы и слоты.

Допустим, у меня есть следующие классы (псевдо-C ++ код):

class Ball
{
    Color m_Color;
    int m_Size;
};

class Player
{
public:
    setBall(Ball* pBall)
    {
        if (pBall != m_pBall)
        {
            Ball* pPreviousBall = m_pBall;
            m_pBall = pBall;
            emit notifyBallNotUsed(pPreviousBall);
        }
    }

    Ball* getBall();

signals:
    void notifyBallNotUsed(Ball*);

private:
    String m_Name;
    Ball* m_pBall;
};

class GeneralHandler
{
public:
    addBall(Ball* pBall);
    deleteBall(Ball* pBall);


    addPlayer(Player* pPlayer)
    {
        connect(pPlayer, SIGNAL(notifyBallNotUsed(Ball*)), this, SLOT(onBallUsageChanged(Ball*)));
        ...
    }
    deletePlayer(Player* pPlayer);
    {
        disconnect(pPlayer, SIGNAL(notifyBallNotUsed(Ball*)), this, SLOT(onBallUsageChanged(Ball*)));

        onBallUsageChanged(pPlayer->getBall());
        ....
    }

private slots:
    void onBallUsageChanged(Ball* pBall)
    {
        if (isNotUsedAnymore(pBall))
        {
            m_BallList.remove(pBall);
            delete pBall;
        }
    }

private:
    bool isNotUsedAnymore(Ball* pBall); // Check if the given ball is still used by at least one player

    List<Player*> m_PlayerList;
    List<Ball*> m_BallList;
};

С моим приложением пользователь может добавлять / удалять игрока, а для каждого игрока решать цвет и размер мяча. За капюшоном GeneralHandler отвечает за хранение шаров и их удаление. Вполне возможно, что два игрока используют один и тот же мяч.

Когда игрок удаляется, если мяч больше не используется, GeneralHandler должен удалить его (или оставить его, если мяч все еще используется другим игроком). Если шар, используемый игроком, заменяется, предыдущий шар, если он больше не используется, также должен быть удален GeneralHandler.

Пока все хорошо.

Теперь я хочу добавить возможность отмены / повтора в мое приложение, используя шаблон команды, и это то, где я застрял. Допустим, у меня есть что-то вроде этого:

class ChangePlayerBall : public QUndoCommand
{
public:
    ChangePlayerBall(Player* pPlayer, Ball* pNewBall)
    {
        m_pPlayer = pPlayer;
    }

    void redo();
    void undo();

private:
    Player* m_pPlayer;
};

Я думаю, метод redo () будет выглядеть так:

void ChangePlayerBall::redo()
{
    m_pPlayer->setBall(pNewBall);
}

Если в приведенном выше коде ничего не изменилось, предыдущий мяч будет удален, если другие игроки больше не будут его использовать. Это будет проблемой при реализации метода undo (): если предыдущий шар был удален, я не знаю, каковы его характеристики, и команда undo не сможет его воссоздать. Или, может быть, я должен сохранить предыдущий мяч, но как команда отмены / повторного выполнения узнает, существует ли этот предыдущий мяч или он был удален обработчиком? Или, может быть, этот механизм удаления шара, как только он больше не используется, должен быть реализован в команде отмены? Проблема в том, что команда отмены будет иметь много зависимостей от многих других классов. Другая проблема заключается в том, что этот код будет частично продублирован в команде DeletePlayer, которая должна будет выполнить нечто подобное:

class DeletePlayer : public QUndoCommand
{
public:
    DeletePlayer(Player* pPlayer);

    void redo();
    void undo();
...
};

Надеюсь, мои объяснения понятны!

Как бы вы решили эту проблему? Я не могу найти удовлетворительное решение.

Спасибо!

Ответы [ 3 ]

1 голос
/ 16 декабря 2008

Мяч будет удален, если не используется больше других игроков

Как я вижу - это s the source of your doubts. Certainly undo() command shouldn't recreate an object nor have it собственный механизм удаления. Как работает ваш GeneralHandler.isNotUsedAnymore ()? Если он считает ссылки на шары, то ссылка на экземпляр ChangePlayerBall также должна учитываться. Поэтому потребуется подключить объект Command к некоторым слотам GeneralHandler.

Итак, я бы предложил:

  1. Мяч удаляется, когда он не используется никакими игроками и любые команды отмены (могут включать изменение цвета и т.д.)
  2. Связь между мячом и тормозами игрока при новом назначении мяча, как вы сделали
  3. Связь между шариковым и командным тормозами в деструкторе объекта команды (когда он полностью удален из стека)

Надеюсь, это поможет)

0 голосов
/ 01 декабря 2010
  1. Сохранить мяч в конструкторе команды.
  2. При необходимости вставьте / выведите.
  3. Используйте QSharedPointer для мяча, чтобы предотвратить утечку памяти
0 голосов
/ 29 мая 2009

Как насчет использования трюка подсчета ссылок для мяча? Когда мяч сохраняется в команде, команда может увеличивать счетчик ссылок для шара, что предотвращает удаление от обработчика (или само по себе, в зависимости от того, как вы изменили бы реализацию).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...