Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
 Аватар для BeginerMan
51 / 50 / 14
Регистрация: 17.11.2012
Сообщений: 427

В зависимости от выбора пользователя, инициализировать один из классов-наследников и использовать только его

01.02.2016, 20:59. Показов 755. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем здрасьте.

У меня такая ситуация:
Есть класс-родитель: Main
Есть много классов-наследников: One, Two, Three, Four .... и т.д.

Теперь проблема:
В зависимости от выбора пользователя, мне нужно инициализировать один из классов-наследников и использовать ТОЛЬКО его. Как мне тут поступить ? Я не могу додумать ....

У меня в коде есть 3 стадии для ВЫБРАННОГО класса-наследников:
1. Инициализация
2. Обновление данных
3. Рисование

Что у меня в голове:
-Описать все классы-наследники(если их будет 50, то ....)
-Завести переменную NUM(будет указывать на какой именно)
-Проверять NUM и использовать только тот класс-наследник, который нужен.

Хотелось бы иметь какой-нибудь указатель, чтобы в него можно было записать класс-наследник, который выбрали.
Не могу додумать как это сделать...

Мой говнокод в голове:
Кликните здесь для просмотра всего текста

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
One* one;
Two* two;
// и так 50 штук
 
void Initialize(int NUM)
{
    if(NUM == 1)
    {
        one = new One;
        one->Init();
    }
    else if(NUM == 2)
    {
        two = new Two;
        two ->Init();
    }
    // И так 50 штук
}
 
void Update(int NUM)
{
    if(NUM == 1)
    {
        one->Update();
    }
    else if(NUM == 2)
    {}
    // И так 50 штук
}
 
void Render()
{
// Здесь собственно тоже самое.
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.02.2016, 20:59
Ответы с готовыми решениями:

Как использовать наследников от стандартных классов? Например, CMyEdit?
Я начал изучать MFC. Программа - простой диалог со строкой ввода. Диалог со строкой ввода нарисовал как ресурс. Мне нужно в clipboard...

Запихивание нескольких классов-наследников в один динамический массив
Снова здравствуйте. У меня есть абстрактный класс Shape, а так же классы Circle и Rectangle, которые его наследуют. Необходимо сделать...

Подключение файла в зависимости от выбора пользователя
Появилась задача. Решить ее можно если подключать нужны файл php в зависимости от выбора пользователя. Есть 3 файла. index.php ...

7
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.02.2016, 21:36
Цитата Сообщение от BeginerMan Посмотреть сообщение
В зависимости от выбора пользователя, мне нужно инициализировать один из классов-наследников и использовать ТОЛЬКО его. Как мне тут поступить ?
рекомендую вам ознакомиться с темой для начинающих "полиморфизм".

http://rextester.com/KGK16013



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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//-------------------------------------------------------------------------        
//---------- кросс-платформенный макрос отображения имени функции ---------
//-------------------------------------------------------------------------        
 
#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW__)
    #define dFUNCTION __PRETTY_FUNCTION__
#else
    #ifdef _MSC_VER
        #define dFUNCTION __FUNCSIG__
    #else
        #define dFUNCTION __FUNCTION__
    #endif
#endif
 
//-------------------------------------------------------------------------         
//-------------------------------------------------------------------------        
//-------------------------------------------------------------------------       
 
#include <unordered_map>
 
// фабрика позволяет создавать наследника
// по символьному имени класса
 
struct ibase;
 
class factory
{
    typedef ibase* (*creator)();
    typedef std::unordered_map<std::string, creator> 
        creators;
 
    static creators& data() 
    {
        static creators data;
        return data;
    }
 
    template<typename T> static ibase* create()
        { return new T; }
public:
    template<typename T>
    static void reg( const std::string& name )
    {
        auto& c = data();
        if( c.cend() == c.find(name) )
            c.emplace( name, &create<T>);
    }
 
    static ibase* create( const std::string& name ) 
    {
        auto& c = data();
        auto it = c.find( name );
        if( c.cend() != it )
            return (it->second)();
        return nullptr;
    }
};
#define REGISTER(cl) factory::reg<cl>( #cl )
 
 
//-------------------------------------------------------------------------         
//-------------------------------------------------------------------------        
//-------------------------------------------------------------------------       
 
 
// теперь определяем базовый интерфейс будущих наследников
struct ibase{
    
    virtual ~ibase(){}
    
    // все эти методы должны будут реализовать наследники
    virtual void init()=0;
    virtual void update()=0;
    virtual void draw()=0;
};
 
//-------------------------------------------------------------------------         
//-------------------------------------------------------------------------        
//-------------------------------------------------------------------------       
 
#include <iostream>
 
// теперь создаем самих наследников
// их может быть 100500
 
#define dFIX std::cout << dFUNCTION << std::endl;
 
class directx : public ibase
{
    virtual void init()   { dFIX; }
    virtual void update() { dFIX; }
    virtual void draw()   { dFIX; }
};
 
class opengl : public ibase
{
    virtual void init()   { dFIX; }
    virtual void update() { dFIX; }
    virtual void draw()   { dFIX; }
};
 
 
struct engine
{
    engine()
    {
        // теперь нужно зарегистрировать всех наследников
        // которые могут быть использованы в работе
        REGISTER(directx);
        REGISTER(opengl);
    }
    
    
    ~engine() { delete device; }
    
    void select(const std::string& name)
    {
        device = factory::create(name);
    }
    
    
    int work()
    {
        dFIX;
        
        if(!device)
            return std::cout<<"error: device not ready\n", 1;
        
        device->init();
        device->update();
        device->draw();
        return 0;
    }
    
private:
    
    ibase* device = nullptr;
};
 
int main()
{
    std::cout << "Hello, world!\n";
    
    std::cout << "input device (directx/opengl):\n";
    std::string name = "directx";
    //std::cin >> name; 
    
    
    engine eng;
    eng.select(name);
    eng.work();
    
}
3
 Аватар для BeginerMan
51 / 50 / 14
Регистрация: 17.11.2012
Сообщений: 427
01.02.2016, 23:40  [ТС]
Уф, сложно разобраться, но я почитал с других источников про Полиморфизм, очень полезно было ознакомится.
Можно сюда пример полегче ?

Давайте я поясню детали моих классов.
Я делаю персонажей, всё то что у этих персонажей общего, я закинул в класс-родитель - Main;
Дальше идут классы-наследники, в этих классах уже индивидуальные способности персонажей - Mage, Warrior, ...

Как я понял, мне в родительском классе нужно создать virtual функции, которые будут в классах-наследниках ?
Такой код сойдёт за годноту ?
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
class Main
{
    /*
    ...
    */
    virtual bool Initialize();
 
    virtual void Ability1();
    virtual void Ability2();
    
    virtual void Cast();
 
protected:
    bool InitBase();
     /*
    ...
    */
};
 
class Mage : public Main
{
    /*
    ...
    */
    bool Initialize() { InitBase(); InitMage(); return true; }
 
    void Ability1();
    void Ability2();
    
    void Cast();
 
private:
    bool InitMage();
     /*
    ...
    */
};
 
 
int main()
{
    Main *Champion = new Mage;
    
    Champion->Initialize();
 
    Champion->Ability1();
    Champion->Cast();
 
}
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
02.02.2016, 00:12
Цитата Сообщение от BeginerMan Посмотреть сообщение
Как я понял, мне в родительском классе нужно создать virtual функции, которые будут в классах-наследниках ?
Такой код сойдёт за годноту ?
похоже на правду,
но строка:

Цитата Сообщение от BeginerMan Посмотреть сообщение
bool Initialize() { InitBase(); InitMage(); return true; }
несколько напрягает.

Не по теме:

что за игру делаете?

0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
02.02.2016, 00:13

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
if( c.cend() == c.find(name) )
c.emplace( name, &create<T>);
Что за магия? :) Как функция вызвалась без круглых скобок?


Цитата Сообщение от BeginerMan Посмотреть сообщение
инициализировать один из классов-наследников и использовать ТОЛЬКО его.
Может быть отражение Вам в помощь?
0
02.02.2016, 00:16

Не по теме:

Цитата Сообщение от gromo Посмотреть сообщение
Что за магия?
"Цэ пись пись"



Не по теме:

Цитата Сообщение от gromo Посмотреть сообщение
Как функция вызвалась без круглых скобок?
C++
1
c.emplace( name, &create<T>);
здесь в карту сохранился pair:
ключ - стринговое имя,
значение - указатель на функцию.

это:
C++
1
&create<T>
взятие адреса функции

0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
02.02.2016, 00:24

Не по теме:

Цитата Сообщение от gromo Посмотреть сообщение
Как функция вызвалась без круглых скобок?
Все понял, это берется адрес инстанции шаблона. Пора спать :umnik:



Не по теме:

Добавлено через 37 секунд

Цитата Сообщение от hoggy Посмотреть сообщение
взятие адреса функции
уже разобрался, спасибо:)



Добавлено через 7 минут
Цитата Сообщение от hoggy Посмотреть сообщение
C++
1
2
typedef ibase* (*creator)();
    typedef std::unordered_map<std::string, creator> creators;
Кстати, по-моему typedef 2.0 всё же читабельнее будет
C++
1
2
using creator = ibase* (*)();
using crators = std::unordered_map<std::string, creator>;
0
 Аватар для BeginerMan
51 / 50 / 14
Регистрация: 17.11.2012
Сообщений: 427
02.02.2016, 11:25  [ТС]
hoggy, Вот тут у меня тоже есть СОМНЕНИЕ, смогу ли я использовать функцию InitializeMage ?
По идеи я беру указатель от класса-родителя Main, не думаю что в смогу вызвать InitializeMage, надо будет проверить ... Можно проще, сделать.
Но спасибо, я более менее разобрался !

Добавлено через 10 часов 23 минуты
hoggy,
Про игру ... обычный платформер, всё уже сделано, кроме персонажей и серв., клиент. частей ...
Вернее даже персонажи сделаны, осталось разобраться с моей проблемой, которая собственно в моих постах
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
02.02.2016, 11:25
Помогаю со студенческими работами здесь

Инициализировать объект в одной форме и использовать его в другой
Здравствуйте! Существует Form1, в которой есть метод, инициализирующий некоторый объект класса MyClass и открывающий вторую форму: ...

Выполнение действия в зависимости от выбора пользователя в confirm.
не получается привязать к confirm действие. По отдельности работает, а когда пытаюсь совместить, то нет. &lt;input...

Функции - сортировка массива в зависимости от выбора пользователя
День добрый, тема, функции и массивы (пузырьки). Сортировка массива в зависимости от выбора пользователя, по убыванию или по возрастанию....

Составьте программу, которая в зависимости от выбора пользователя
Помогите пожалуйста решить 3 задачки

Реализация классов-наследников или классов-родителей
Не могу переделать функционал программы таким образом, чтобы у появились классы-наследники, или классы-родители со своими методами. ...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru