Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.53/15: Рейтинг темы: голосов - 15, средняя оценка - 4.53
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521

ООП и паттерн Стратегия

20.03.2019, 13:16. Показов 3905. Ответов 46
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день! Помогите, пожалуйста, изучаю объектно-ориентированное программирование и паттерн Стратегия. В задаче есть два типа объектов. У них по 2 поля совпадают. А третье разное. Нужно, чтобы объекты первого типа обрабатывала стратегия 1. А второго - стратегия 2. В коде ниже создала абстрактный класс Strategy. В нем сделала функцию corr без реализации. В классе Strategy1 сделала, чтобы функция corr принимала объекты 1 типа и выводила их поля, а в классе Strategy2, чтобы функция corr принимала объекты 2 типа и выводила их поля. Почему-то компилятор считает классы Strategy1 и Strategy2 абстрактными. Видимо, потому что в corr передаются разные параметры. Хотя классы Type1 и Type2 наследники класса Type. Как можно реализовать, чтобы выбиралась стратегия в зависимости от типа?
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
class Strategy
 
{
 
    public:
 
           virtual ~Strategy() {} //деструктор
 
           virtual void corr(Type t) = 0;
 
};
 
class Strategy1 : public Strategy
 
{
 
    public:
 
           void corr(Type1 a)
 
           {
 
                printf("Strategy1\n свойство1=%f, свойство2=%f, тип объекта=1, par1=%f", a.pr1, a.pr2, a.par1);
 
           }
 
};
 
class Strategy2 : public Strategy
 
{
 
    public:
 
           void corr(Type2 b)
 
           {
 
               printf("Strategy2\n свойство1=%f, свойство2=%f, тип объекта=2, par2=%f", b.pr1, b.pr2, b.par2);
 
           }
 
};
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.03.2019, 13:16
Ответы с готовыми решениями:

Паттерн стратегия
Всем привет! Начал изучать паттерны. Одним из наиболее понятных и интересных мне оказался паттерн Стратегия. Я начитался статей и...

Паттерн Стратегия на примере сортировки
Всем привет! Видел множество примеров по паттерну Стратегия, но не встречал пример со сортировкой, может у кого-нибудь есть реализованный...

Паттерн стратегия и ошибки при компиляции
Здравствуйте уважаемые форумчане. Вот решил я как-то недавно, что мой код говно и надо что-то с этим делать, так как я пишу нормальные по...

46
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
22.03.2019, 19:01
Студворк — интернет-сервис помощи студентам
Simply me, вот держите
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
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
namespace test {    
    
struct stream {
    virtual ~stream() {}
    virtual void print() noexcept = 0;
protected:
    float pressure_;
    float temperature_;
};
    
struct stream_type_b final : stream {
    stream_type_b(std::stringstream& ss) noexcept {
        ss >> pressure_; 
        ss >> temperature_;
        ss >> parameter_;
    }
    
    void print() noexcept override {
        std::cout << pressure_ << ' ' << temperature_ << ' ' << parameter_ << '\n';
    }
private:
    int parameter_;
};
    
struct stream_type_c final : stream {
    stream_type_c(std::stringstream& ss) noexcept {
        ss >> pressure_; 
        ss >> temperature_;
        ss >> parameter_;
    }
    
    void print() noexcept override {
        std::cout << pressure_ << ' ' << temperature_ << ' ' << parameter_ << '\n';
    }
private:
    int parameter_;
};
    
stream* make_stream(std::stringstream& ss) { // фабричный метод, типо
    if (ss.str().front() == 'B') { 
        ss.ignore(1, 'B');
        return new(std::nothrow) stream_type_b(ss);
    } else {
        ss.ignore(1, 'C');
        return new(std::nothrow) stream_type_c(ss);
    }
}
    
}
 
int main() {
    std::vector<test::stream*> stream_list;
    std::ifstream              fin("имя_файла.расширение");
    std::string                line;
    if (fin) {
        while (std::getline(fin, line)) { // разбиваем по строкам
            std::stringstream ss(line); // здесь находится вся строка
            stream_list.push_back(test::make_stream(ss));
            // ...
        }
    }
    // ...
}
1
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
22.03.2019, 19:04  [ТС]
Azazel-San, спасибо большое!
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
22.03.2019, 19:08
Simply me, доделайте мой пример, там буквально заменить "имя_файла.расширение" на ваш реальный файл и после if (fin) добавить цикл по выводу, как-то так:
C++
1
2
3
for (auto&& stream : stream_list) {
    stream->print();
}
И отпишите работает ли мой пример, если да, то можете смотреть на мой пример и переделать под свой.
0
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
22.03.2019, 19:09  [ТС]
Хорошо)
0
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
24.03.2019, 10:35  [ТС]
Azazel-San, сейчас проверила. Спасибо большое! Всё работает! Скриншот во вложении. Здесь окончательный вариант кода.

Не по теме:

Пока немного не понимаю некоторые конструкции для работы с объектами stringstream:
ss >> pressure для заполнения поля из потока,
new(std::nothrow) (вместо просто new),
ss.str().front() для обращения к первому символу строки, но, думаю, привыкну)


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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "stdafx.h"
#include <sstream>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
 
//Базовый класс для всех типов потоков
class Stream
{
public:
    double pressure;
    double temperature;
    Stream() //конструктор
    {
        pressure = 0; //значения по умолчанию
        temperature = 0;
    }
    virtual ~Stream() {} //деструктор
    virtual void corr() = 0; //функция расчета корреляций, реализуется в зависимости от типа потока
};
 
//Поток B
class StreamB : public Stream
{
    public:
        double parameter;
        StreamB(std::stringstream& ss) //конструктор
        {
            ss >> pressure;
            ss >> temperature;
            ss >> parameter;
        }
        virtual ~StreamB() {} //деструктор
        virtual void corr()
        {
            std::cout << "StrategyB " << pressure << ' ' << temperature << ' ' << parameter << ' ' << '\n';
        }
};
 
//Поток С
class StreamC : public Stream
{
    public:
        double parameter;
        StreamC(std::stringstream& ss) //конструктор
        {
            ss >> pressure;
            ss >> temperature;
            ss >> parameter;
        }
        virtual ~StreamC() {} //деструктор
        virtual void corr()
        {
            std::cout << "StrategyC " << pressure << ' ' << temperature << ' ' << parameter << ' ' << '\n';
        }
};
 
//Класс для заполнения параметров потоков из файла
class StreamDataFromFile
{
    public:
        std::vector<Stream*> StreamList; //список потоков
        Stream* createStream(std::stringstream& ss) //функция создания потока
        {
            if (ss.str().front() == 'B') 
            {
                ss.ignore(1, 'B');
                return new(std::nothrow) StreamB(ss);
            }
            else 
            {
                ss.ignore(1, 'C');
                return new(std::nothrow) StreamC(ss);
            }
        }
        std::vector<Stream*> FillFromFile(std::string fn) //функция для заполнения полей потоков из файла
        {
            std::ifstream fin(fn);
            std::string   line;
            if (!fin)
            {
                std::cout << "File is not open";
            }
            else
            {
                while (std::getline(fin, line)) //разбиение по строкам
                {
                    std::stringstream ss(line);
                    if ((ss.str().front() == 'B') || (ss.str().front() == 'C'))
                        StreamList.push_back(createStream(ss));
                }
                fin.close();
            }
            return StreamList;
        }
};
 
int main()
{
    setlocale(LC_ALL, "rus");
    std::vector<Stream*> v;
    std::vector<Stream*>::iterator iter;
    std::string filename;
    std::cout << "Input filename" << "\n";
    std::cin >> filename;
    StreamDataFromFile MyStreamData;
    v=MyStreamData.FillFromFile(filename);
    for (iter = v.begin(); iter != v.end(); ++iter)
    {
        Stream* MyStream = *iter;
        MyStream->corr();
    }
    system("Pause");
    return 0;
}
Миниатюры
ООП  и паттерн Стратегия  
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
24.03.2019, 19:25
Цитата Сообщение от Simply me Посмотреть сообщение
Всё работает!
Значит мой вариант тоже был рабочим?
Цитата Сообщение от Simply me Посмотреть сообщение
ss >> pressure
Все довольно просто, таким образом мы записываем данные из потока в переменную, чтение происходит до пробела.
Цитата Сообщение от Simply me Посмотреть сообщение
new(std::nothrow) (вместо просто new)
Вы, можете убрать, в вашем случае это не критично, я это делал потому что у меня функция была noexcept, - т.е. этот оператор говорит, что ф-я не будет бросать исключений (которые например может бросить обычный new), а если бросит тогда наша программа сразу же упадет в std::terminate, таким образом нам надо сделать так что бы new не бросал исключений, где конструкция new(std::nothrow) это и делает, т.е. исключение в случае неудачи брошено не будет, а просто вернется nullptr указатель.

З.ы. - сейчас увидел что она у меня на самом деле не noexcept
Цитата Сообщение от Simply me Посмотреть сообщение
ss.str().front() для обращения к первому символу строки
Да, верно.
Цитата Сообщение от Simply me Посмотреть сообщение
C++
1
class Stream
Раз Вы делаете класс, то делайте его поля приватными, если Вы хотите что бы они были публичными успользуйте структуры struct, тогда как минимум не придется писать лишний раз public.

При переопределении виртуальных методов в наследнике лучше писать так:
C++
1
void corr() override { /* ... */ }
вместо
Цитата Сообщение от Simply me Посмотреть сообщение
C++
1
virtual void corr()
...
Цитата Сообщение от Simply me Посмотреть сообщение
C++
1
class StreamDataFromFile
Еще весьма странное названия для класса и совсем не отражает то что делает класс, а он ответственен за создание и потока и за заполнение из файла, что наверное не совсем верно.
Цитата Сообщение от Simply me Посмотреть сообщение
if ((ss.str().front() == 'B') || (ss.str().front() == 'C'))
Здесь лишняя проверка, в методе createStream, мы делаем тоже самое.
Как-то так.
1
 Аватар для Simply me
244 / 37 / 8
Регистрация: 05.05.2012
Сообщений: 521
24.03.2019, 20:02  [ТС]
Цитата Сообщение от Azazel-San Посмотреть сообщение
Значит мой вариант тоже был рабочим?
Да, Ваш код тоже рабочий) В основном добавила #include "pch.h". В моей VS без нее не работает. setlocale(LC_ALL, "rus") для отображения кириллицы, вывод типа потока, ввод имени файла пользователем, чтение из файла убрала из main и свои обозначения.

Спасибо за объяснения!)

Цитата Сообщение от Azazel-San Посмотреть сообщение
используйте структуры struct,
Да, надо бы. Прочитала C++ для чайников Стефана Ренди Дэвиса. Там он объясняет разницу между class и struct насчет public и private по умолчанию. Но говорит, что сам в этой книжке будет использовать только class. Поэтому не привыкла)

Исправлю замечания)

Цитата Сообщение от Azazel-San Посмотреть сообщение
Здесь лишняя проверка
Хотела, чтобы шапка не выводилась. Типа не поток ведь. А потом подумала, что без шапки ненаглядно. Добавила такое else:
C++
1
2
3
4
5
6
7
8
while (std::getline(fin, line)) //разбиение по строкам
       {
           std::stringstream ss(line);
           if ((ss.str().front() == 'B') || (ss.str().front() == 'C'))
               StreamList.push_back(createStream(ss));
           else
            std::cout << line << "\n";
        }
В общем, да, надо вернуть как было, убрать лишнюю проверку и это else
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.03.2019, 20:02

Сделать выбор персонажа игры, вывод его скилов и предметов, используя паттерн стратегия
В лабе надо было сделать выбор персонажа игры,вывод его скилов и предметов,используя паттерн стратегия.В VS программа вроде...

С++ Паттерн "стратегия". Проблема
Добрый день. Начал изучать паттерны проектирования, столкнулся с шаблоном &quot;Стратегия&quot;. Решение конкретно моей проблемы в интернете не...

Стратегия выборки
Используя один из языков высокого уровня составить модель стратегии операционной системы для управления виртуальной памятью. Условия...

Пошаговая стратегия (начало)
ребят тут такое дело. мне нужно написать пошаговую стратегию(для начала элементарную) на языке с++. для начала нужно создать 1)Класс...

Пошаговая стратегия(начало)
ребят тут такое дело. мне нужно написать пошаговую стратегию на языке с++. для начала нужно создать 1)Класс игровое поле (назовем его...


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

Или воспользуйтесь поиском по форуму:
47
Ответ Создать тему
Новые блоги и статьи
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru