Объект доступа инициализируется в блоке try после этого, если не возникло исключение

У меня есть вариант использования, когда я пытаюсь инициализировать Player объект в try блокировать. Соответствующий отрывок из текущий, рабочий код выглядит следующим образом:

string GameServer::processMapRequest(MapRequest const &request) const
{
    MapResponse response;
    response.header.playerId = request.header.playerId;
    auto playerId = static_cast<unsigned long>(request.header.playerId);
    Player otherPlayer;

    try {
        otherPlayer = Player(getPlayer(playerId));
    } catch (NoSuchPlayer&) {
        return serialize(InvalidRequest());
    }

    PlayerBoard targetBoard = otherPlayer.getBoard();
    response.width = targetBoard.getWidth();
    response.height = targetBoard.getHeight();
    string targetBoardMap = targetBoard.toString();
    response.size = static_cast<uint32_t>(targetBoardMap.size());
    string buf = serialize(response);
    buf += targetBoardMap;
    return buf;
}

Меня беспокоит то, что мне пришлось добавить конструктор без аргументов в Player для инициализации переменной перед блоком try-catch.

Варианты, которые я рассмотрел:

  1. Объявите переменную в блоке try. Но тогда он будет ограничен своей областью действия, и мне также придется переместить всю обработку в этот блок, что загромождает его и делает неоднозначным относительно того, какой оператор там может вызвать исключение.
  2. Передайте обработку под блоком try-catch отдельной функции, которая принимает игрока в качестве аргумента и вызывает его в блоке try. Это добавит необходимости в другой функции-члене, а также загромождает блок try, как в 1.
  3. Используйте какие-то умные указатели C ++. К сожалению, я не уверен, какой из них использовать здесь и как это сделать правильно (здесь новичок в C ++).

tl; dr можно ли сохранить общую структуру функции и инициализировать заполнитель для инициализируемого объекта игрока в блоке try, чтобы его можно было использовать после блока catch?

Дополнение

Рассматриваемый агрегат целиком:

//
// Created by rne on 08.05.21.
//

#include <memory>
using std::unique_ptr;

#include <stdexcept>
using std::out_of_range;

#include <string>
using std::string;

#include <utility>
using std::move;

#include <vector>
using std::vector;

#include "Ship.h"
using models::ShipTypes;

#include "util.h"
using util::contains;
using util::copyString;

#include "PlayerBoard.h"
using models::PlayerBoard;

#include "Constants.h"
#include "Server.h"
using net::Server;

#include "Messages.h"
#include "NoSuchPlayer.h"
#include "Player.h"

#include "GameServer.h"

namespace proto {
    GameServer::GameServer(string const &host, unsigned short port, ShipTypes shipTypes)
            : Server(host, port), players(Players()), shipTypes(move(shipTypes)),
            state(GameState::WAITING_FOR_PLAYERS)
    {}

    GameServer::GameServer(string const &host, unsigned short port)
            : GameServer(host, port, models::Constants::shipTypes)
    {}

    GameServer::GameServer(ShipTypes shipTypes)
            : Server(), shipTypes(move(shipTypes))
    {}

    GameServer::GameServer()
            : GameServer(models::Constants::shipTypes)
    {}

    Player GameServer::getPlayer(unsigned long playerId) const
    {
        for (Player const &player : players) {
            if (player.getId() == playerId)
                return player;
        }

        throw NoSuchPlayer(playerId);
    }

    string GameServer::processLoginRequest(LoginRequest const &request)
    {
        LoginResponse response;
        response.header.playerId = request.header.playerId;
        string playerName = request.playerName;

        if (players.size() < 2) {
            players.push_back(Player(players.size() + 1, playerName));
            response.header.playerId = players.size();
            response.accepted = true;
        }

        return serialize(response);
    }

    string GameServer::processShipTypesRequest(ShipTypesRequest const &request) const
    {
        ShipTypesResponse response;
        response.header.playerId = request.header.playerId;
        response.ships = static_cast<uint8_t>(shipTypes.size());
        string buf = serialize(response);

        for (auto &[name, size] : shipTypes) {
            ShipType shipType;
            copyString(shipType.name, name, sizeof shipType.name);
            shipType.size = static_cast<uint8_t>(size);
            buf += serialize(shipType);
        }

        return buf;
    }

    string GameServer::processMapRequest(MapRequest const &request) const
    {
        MapResponse response;
        response.header.playerId = request.header.playerId;
        auto playerId = static_cast<unsigned long>(request.header.playerId);
        Player otherPlayer;

        try {
            otherPlayer = Player(getPlayer(playerId));
        } catch (NoSuchPlayer&) {
            return serialize(InvalidRequest());
        }

        PlayerBoard targetBoard = otherPlayer.getBoard();
        response.width = targetBoard.getWidth();
        response.height = targetBoard.getHeight();
        string targetBoardMap = targetBoard.toString();
        response.size = static_cast<uint32_t>(targetBoardMap.size());
        string buf = serialize(response);
        buf += targetBoardMap;
        return buf;
    }

    string GameServer::processShipPlacementRequest(ShipPlacementRequest const &request) const
    {
        ShipPlacementResponse response;
        return serialize(response);
    }

    string GameServer::processStatusRequest(StatusRequest const &statusRequest) const
    {
        StatusResponse response;
        return serialize(response);
    }

    string GameServer::processTurnRequest(TurnRequest const &turnRequest) const
    {
        TurnResponse response;
        return serialize(response);
    }

    string GameServer::handleRequest(string const &buf)
    {
        RequestHeader header = deserialize<RequestHeader>(buf, true);
        InvalidRequest invalidRequest;

        switch (header.type) {
            case RequestType::LOGIN_REQUEST:
                return processLoginRequest(deserialize<LoginRequest>(buf));
            case RequestType::SHIP_TYPES_REQUEST:
                return processShipTypesRequest(deserialize<ShipTypesRequest>(buf));
            case RequestType::MAP_REQUEST:
                return processMapRequest(deserialize<MapRequest>(buf));
            case RequestType::SHIP_PLACEMENT_REQUEST:
                return processShipPlacementRequest(deserialize<ShipPlacementRequest>(buf));
            case RequestType::STATUS_REQUEST:
                return processStatusRequest(deserialize<StatusRequest>(buf));
            case RequestType::TURN_REQUEST:
                return processTurnRequest(deserialize<TurnRequest>(buf));
            default:
                return serialize(invalidRequest);
        }
    }
}
```

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *