0 / 0 / 0
Регистрация: 07.08.2019
Сообщений: 13
1

Проблема с умным указателем std::unique_ptr

18.08.2019, 15:12. Показов 419. Ответов 2
Метки нет (Все метки)

здравствуйте. есть задание - написать небольшую простенькую игру, где есть базовый класс Unit, кроме него есть ещё три класса - Swordsman(мечник), Archer(лучник), Mage(маг), которые наследуются от класса Unit. Так же есть класс Team, то есть команда, с приватным полем - вектором из юнитов. в конструкторе данного класса в вектор рандомно добавляются мечник, лучник или маг. класс Game - это класс, где и есть метод Figth(). по нажатию клавиши "пробел" происходит атака, то есть вызывается функция Attack() из класса Team. проблема связана именно с этой функцией. вот код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Unit.h
#pragma once
#ifndef UNIT_H
#define UNIT_H
 
class Unit abstract
{
public:
    Unit(double hp, double damage, size_t avoidance);
 
    const size_t GetHp() const { return hp; }
    const size_t GetDamage() const { return damage; }
    const size_t GetAvoidance() const { return avoidance; }
 
    void SetHp(const double hp) { hp < 0 ? this->hp = hp * -1 : this->hp = hp; }
    void SetDamage(const double damage) { damage < 0 ? this->damage = damage * -1 : this->damage = damage; }
    void SetAvoidance(const size_t avoidance) { this->avoidance = avoidance; }
 
private:
    double hp;
    double damage;
    size_t avoidance;
 
};
 
#endif


C++
1
2
3
4
5
6
7
// Unit.cpp
#include "Unit.h"
 
Unit::Unit(double hp, double damage, size_t avoidance)
{
    SetHp(hp), SetDamage(damage), SetAvoidance(avoidance);
}

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Swordsman.h
#pragma once
#ifndef SWORDSMAN_H
#define SWORDSMAN_H
#include "Unit.h"
 
class Swordsman : public Unit
{
public:
    Swordsman() : Unit(15, 5, 60) {}
 
};
 
#endif


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Archer.h
#pragma once
#ifndef ARCHER_H
#define ARCHER_H
#include "Unit.h"
 
class Archer : public Unit
{
public:
    Archer() : Unit(12, 4, 40) {}
 
};
 
#endif


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Mage.h
#pragma once
#ifndef MAGE_H
#define MAGE_H
#include "Unit.h"
 
class Mage : public Unit
{
public:
    Mage() : Unit(8, 10, 30) {}
 
};
 
#endif


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Team,h
#pragma once
#ifndef TEAM_H
#define TEAM_H
#include <vector>
#include <memory>
#include <string>
#include <iostream>
#include <typeinfo>
#define DEFAULT std::vector<std::unique_ptr<Unit>>()
#define UNITS_COUNT 5
#include "Unit.h"
#include "Swordsman.h"
#include "Mage.h"
#include "Archer.h"
 
class Team
{
public:
    Team(std::string _name = "noname", std::vector<std::unique_ptr<Unit>> _units = DEFAULT);
 
    const std::vector<std::unique_ptr<Unit>> GetUnits() const { return units; }
 
    bool TeamDead() const;
    void ShowTeam() const;
 
    static void Attack(std::unique_ptr<Unit> unit1, std::unique_ptr<Unit> unit2);
 
    Team operator=(const Team& other);
 
private:
    std::string name;
    std::vector<std::unique_ptr<Unit>> units;
 
};
 
#endif


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Team.cpp
#include "Team.h"
 
Team::Team(std::string _name, std::vector<std::unique_ptr<Unit>> _units)
{
    units.resize(UNITS_COUNT);
 
    if (units.size() == _units.size())
        units = _units;
    else
        if (_units == DEFAULT)
            for (size_t i = 0; i < units.size(); i++)
                switch (rand() % 3)
                {
                case 0:
                    units.push_back(std::make_unique<Swordsman>());
                    break;
 
                case 1:
                    units.push_back(std::make_unique<Archer>());
                    break;
 
                case 2:
                    units.push_back(std::make_unique<Mage>());
                    break;
                }
}
 
bool Team::TeamDead() const
{
    for (size_t i = 0; i < units.size(); i++)
        if (units[i]->GetHp() != 0)
            return false;
 
    return true;
}
 
void Team::ShowTeam() const
{
    for (size_t i = 0; i < units.size(); i++)
        std::cout << "Class: " << typeid(units[i]).name() << ".\tHP: " << units[i]->GetHp()
        << ".\tDamage: " << units[i]->GetDamage() << ".\tAvoidance chance: " << units[i]->GetAvoidance() << "%.\n";
}
 
void Team::Attack(std::unique_ptr<Unit> unit1, std::unique_ptr<Unit> unit2)
{
    unit1->SetHp(unit1->GetHp() - (unit2->GetDamage() / 100 * unit1->GetAvoidance())), 
        unit2->SetHp(unit2->GetHp() - (unit1->GetDamage() / 100 * unit2->GetAvoidance()));
}
 
Team Team::operator=(const Team & other)
{
    name = other.name,
        units = other.units;
}


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Game.h
#pragma once
#ifndef GAME_H
#define GAME_H
#include "Team.h"
 
class Game
{
public:
    Game(std::string _team1_name = "Radiance", std::vector<std::unique_ptr<Unit>> _units1 = DEFAULT, std::string _team2_name = "Dire",
        std::vector<std::unique_ptr<Unit>> _units2 = DEFAULT);
    Game(const Team& _team1, const Team& _team2);
 
    size_t Fight();
 
private:
    Team team1, team2;
 
};
 
#endif


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Game.cpp
#include "Game.h"
 
Game::Game(std::string _team1_name, std::vector<std::unique_ptr<Unit>> _units1, std::string _team2_name, std::vector<std::unique_ptr<Unit>> _units2)
{
    team1 = Team(_team1_name, _units1),
        team2 = Team(_team2_name, _units2);
}
 
Game::Game(const Team& _team1, const Team& _team2)
{
    team1 = _team1,
        team2 = _team2;
}
 
size_t Game::Fight()
{
    while (team1.TeamDead() || team2.TeamDead())
    {
        if (std::cin.get() == ' ')
        {
            for (size_t i = 0; i < UNITS_COUNT; i++)
                if (typeid(team1.GetUnits()[i]) == typeid(team2.GetUnits()[i]))
                    Team::Attack(team1.GetUnits()[i], team2.GetUnits()[i]);
                else
                    Team::Attack(team1.GetUnits()[i], team2.GetUnits()[rand() % UNITS_COUNT]);
        }
    }
}
как я понял, компилятор ругается на то, что конструктор и перегрузка оператора "=" для класса unique_ptr - удалённые. помогите пожалуйста решить эту проблему.
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.08.2019, 15:12
Ответы с готовыми решениями:

Как достать значение из вектора с умным указателем?
vector&lt;shared_ptr&lt;int&gt;&gt;arr; arr.push_back(make_shared&lt;int&gt;(4)); auto it = arr.begin(); Как...

Как правильно обратиться к элементам полиморфного вектора (с умным указателем)?
Здравствуйте, по заданию нужно: создать абстрактный класс с функцией - норма, определить функцию...

Использование std::unique_ptr
Есть в коде подобная конструкция, вылетает исключение на этапе очистки памяти. С чем это может быть...

Std::unique_ptr virtual метод
#include &lt;iostream&gt; #include &lt;memory&gt; class Base { public: virtual void f1(); // Virtual...

2
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
19.08.2019, 09:38 2
Цитата Сообщение от kurdupl1k Посмотреть сообщение
как я понял, компилятор ругается на то, что конструктор и перегрузка оператора "=" для класса unique_ptr - удалённые. помогите пожалуйста решить эту проблему.

Когда ты передаёшь std::vector<std::unique_ptr по значению, надо делать std::move
C++
1
2
3
4
5
Game::Game(std::string _team1_name, std::vector<std::unique_ptr<Unit>> _units1, std::string _team2_name, std::vector<std::unique_ptr<Unit>> _units2)
{
    team1 = Team(_team1_name, std::move(_units1)),
        team2 = Team(_team2_name, std::move(_units2));
}
C++
1
2
3
4
5
6
7
8
9
eam::Team(std::string _name, std::vector<std::unique_ptr<Unit>> _units)
{
    //units.resize(UNITS_COUNT);
 
    if (_units.size() == UNITS_COUNT)
        units = std::move(_units);
    else
   {
       units.reserve(UNITS_COUNT);
Добавлено через 2 минуты
Цитата Сообщение от kurdupl1k Посмотреть сообщение
if (_units == DEFAULT)
Вместо этого можно сделать if (_units.empty())
0
303 / 215 / 74
Регистрация: 23.05.2011
Сообщений: 971
19.08.2019, 14:06 3
kurdupl1k, по-моему, в твоём случае намного логичнее использовать какой-нибудь shared_ptr.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.08.2019, 14:06

Копирование объектов std::unique_ptr
привет, столкнулся с такой ситуацией, что вроде как копировать объекты std::unique_ptr запрещено,...

Компилятор не видит std::unique_ptr
Не создается unique_ptr int main(int argc, char *argv) { QCoreApplication a(argc, argv);...

Копирование std::unique_ptr в структуре
Есть структуры и vector struct myStruct { int a; int b; void* param; }; struct sSetup {...

Отсутствует std::unique_ptr gcc 4.8.1
всем привет , я в С++ начинающий и возникла проблема не работает std::unique_ptr версия...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.