Лучший способ инициализировать элемент std :: array, который имеет конструктор не по умолчанию? - PullRequest
0 голосов
/ 14 июля 2020

В настоящее время при инициализации массива basicEnemies мне нужно передать audioManager конструктору каждого класса basicEnemy . Однако у меня есть 20 basi c врагов, так что есть лучший способ инициализировать каждого basicEnemy из MainGameScene без необходимости повторять переход audioManager в конструктор, как я это делаю ? Конструктор для каждого basicEnemy должен быть вызван.

MainGameScene.h
MainGameScene(AudioManager *audioManager)
std::array<BasicEnemy, 20> basicEnemies;
MainGameScene.cpp
MainGameScene::MainGameScene(AudioManager *audioManager) : basicEnemies{audioManager, audioManager, audioManager, audioManager...}
{
}
BasicEnemy.h
BasicEnemy(AudioManager *audioManager)

Если не слишком много, чтобы спросить, что это за часть ':' после вызова конструктора MainGameScene или как это называется, чтобы в следующий раз я мог спросить точнее?

Ответы [ 3 ]

1 голос
/ 14 июля 2020

Если вы настаиваете на элементе данных std::array<BasicEnemy>, вы можете использовать дополнительный уровень косвенности и std::index_sequence:

class MainGameScene {
private:
    static constexpr std::size_t n_enemies = 20;
    std::array<BasicEnemy, n_enemies> basicEnemies;

    template<std::size_t... is>
    MainGameScene(AudioManager* audioManager, std::index_sequence<is...>) :
        basicEnemies{(is, audioManager)...}
    {}

public:
    MainGameScene(AudioManager* audioManager) : 
        MainGameScene(audioManager, std::make_index_sequence<n_enemies>{})
    {}
};

Если вы можете ослабить требования к типу элемента данных вместе с std::shared_ptr (который выделяется в куче), другой вариант - std::optional (который сохраняет объект внутри себя):

class MainGameScene {
private:
    std::array<std::optional<BasicEnemy>, 20> basicEnemies;

public:
    MainGameScene(AudioManager* audioManager) {
        std::fill(basicEnemies.begin(), basicEnemies.end(), audioManager);
    }
}; 
0 голосов
/ 14 июля 2020

Добавьте значение по умолчанию для параметра, который вызывает глобальную фабричную функцию:

 BasicEnemy(AudioManager *audioManager = getAudioManager() )
0 голосов
/ 14 июля 2020

Вы можете их сгенерировать:

MainGameScene::MainGameScene(AudioManager *audioManager) 
{
    std::generate(basicEnemies.begin(), basicEnemies.end(), [&audioManager]() {
         return BasicEnemy(audioManager);
    }
}
...