Форум программистов, компьютерный форум CyberForum.ru

Группировка функций разных классов - C++

Восстановить пароль Регистрация
 
gameman
0 / 0 / 0
Регистрация: 23.02.2012
Сообщений: 6
23.02.2012, 18:35     Группировка функций разных классов #1
Всем привет!

Возник спорный вопрос. Задача:
Есть много классов, но у каждого из них может быть (! а может и нет) по методу, например, следующий набор: fnc1, fnc2, fnc3. Программа должна вызвать эти функции независимо от класса и его свойств. Точнее в программе создаются по 1 (скорее по нескольку) экземпляров классов, а программа должна вызвать у каждого из них один и тот же метод.

Я нашел только 2 решения: использовать указатели на статические функции (пихать их в массив и не задумываться) и использовать чистые виртуальные функции (Есть некий класс-"шаблон" с чистыми вирт. функциями, который наследуется всеми остальными. А дальше просто пихаю указатели на экземпяры классов в массив, и вызываю необходимые методы в виде
C++
1
((Parent *)pointer)->fnc();
), но как тогда быть если какой-то функции нет в классе?

И еще вопрос: что быстрее? Мне важна даже самая капелька времени.

Зачем это нужно? Это нужно когда основная программа не должна знать и заботиться о других классах. Что, в свою очередь, необходимо для быстрого расширения спектра возможностей.

Спасибо за внимание!
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,511
23.02.2012, 18:39     Группировка функций разных классов #2
Цитата Сообщение от gameman Посмотреть сообщение
но как тогда быть если какой-то функции нет в классе?
Если вы о использовании полиморфизма то чтобы такого не было делают родительский полностью виртуальный класс с какой-то функцией, а все классы наследники уже потом определяют её. Пример нужен или и так понятно?

Добавлено через 1 минуту
Цитата Сообщение от gameman Посмотреть сообщение
И еще вопрос: что быстрее?
Ну так замерьте же время, проделайте так 100 (или 1000) операций и так и сравните время выполнения Я лишь знаю что виртуальные таблицы вещь не очень быстрая по сравнению с обычными вызовами, но в цифрах ничего сказать не могу.
gameman
0 / 0 / 0
Регистрация: 23.02.2012
Сообщений: 6
23.02.2012, 18:44  [ТС]     Группировка функций разных классов #3
Цитата Сообщение от Gepar Посмотреть сообщение
Если вы о использовании полиморфизма то чтобы такого не было делают родительский полностью виртуальный класс с какой-то функцией, а все классы наследники уже потом определяют её. Пример нужен или и так понятно?
Вы имеете в виду делать не чистые, а простые виртуальные функции, которые ничего не делают? Нет, пример не нужен, спасибо.

Добавлено через 3 минуты
Цитата Сообщение от Gepar Посмотреть сообщение
Ну так замерьте же время, проделайте так 100 (или 1000) операций и так и сравните время выполнения Я лишь знаю что виртуальные таблицы вещь не очень быстрая по сравнению с обычными вызовами, но в цифрах ничего сказать не могу.
Так в том то и дело! Я делал замер на 10 млн. вызовов, и время практически одинаковое. Что с оптимизациями, что без. Из-за погрешностей, там то одни функции опережали, то другие, но разница была все равно незначительной. Да нет проблем использовать статику, но ведь код становится куда красивее и приятнее с использованием виртуалок. Но как я и сказал, мне дорога каждая капля времени. Да и мб есть еще какие способы?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
23.02.2012, 18:55     Группировка функций разных классов #4
gameman, если встают такие проблемы - значит архитектура изначально была неверной. Чтобы всё было красиво с точки зрения проектирования, надо вводить дополнительные промежуточные классы в иерархию, которые будут добавлять к предкам новые методы, и наследовать нужные конкретные классы от этих промежуточных. Чтобы всё красиво вызывалось, когда надо, следует использовать dynamic_cast и смотреть, подклассом какой ветви в иерархии является тип конкретного объекта, и в зависимости от этого вызывать нужные методы. Но вот как это отразится на производительности...
gameman
0 / 0 / 0
Регистрация: 23.02.2012
Сообщений: 6
23.02.2012, 19:18  [ТС]     Группировка функций разных классов #5
silent_1991, Могу привести пример.
Есть игра. Есть различные предметы, например: стул, чашка, дверь.
Есть действия пользователя и функции, обрабатывающие их, например: Левый клик мыши по предмету - LClick()
Есть методы прорисовки в буфер - Draw()
Так вот, я же не буду делать вот так:

C++
1
2
3
4
5
for(i = 0; i < кол-во объектов; i++){
    if(obj[i].type == "стул")
        ((Стул *)obj[i].pointer)->Draw();
    // ... и так далее для каждого типа
}
Дверь имеет обработчика левого клика, а вот стул и чашка - нет.
И вот по добавлению каждого нового предмета в игру я должен буду менять внутренности игры? Мне это кажется нелогичным.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
23.02.2012, 19:22     Группировка функций разных классов #6
gameman, нет, не будете. Потому что, я полагаю, любой игровой объект умеет рисоваться. Поэтому метод draw стоит вынести в самый корневой класс, что даст гарантию, что этот метод есть в любом наследнике. Но стул не умеет испускать свет, поэтому любой объект, который мы хотим "включить" на освещение, должен быть проверен на принадлежность соответствующему уровню иерархии.
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,511
23.02.2012, 19:23     Группировка функций разных классов #7
gameman, так вы ещё и поле тип добавили в каждый класс, мда ...
Почитайте что-то по с++ по полиморфизму, Страуструпа например.
gameman
0 / 0 / 0
Регистрация: 23.02.2012
Сообщений: 6
23.02.2012, 19:28  [ТС]     Группировка функций разных классов #8
Цитата Сообщение от silent_1991 Посмотреть сообщение
вынести в самый корневой класс
Так вот это и есть один из вариантов решения - наследование. А дабы избавиться от if'ов, возникла идея использовать виртуальные функции.

Только я не создаю по каждому экземпляру класса для каждого объекта, а передаю в качестве аргументов только их параметры.

Главной целью стоит избежать этих самых if'ов! Да выгодно: 1) Скорость не зависит от количества объектов. 2) При добавлении новых предметов нет необходимости лезть в дебри движка.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
23.02.2012, 19:30     Группировка функций разных классов #9
gameman, ифов не избежать, потому что какие-то действия нужно проделать только для объектов одних типов, какие-то - для других.
gameman
0 / 0 / 0
Регистрация: 23.02.2012
Сообщений: 6
23.02.2012, 19:44  [ТС]     Группировка функций разных классов #10
Цитата Сообщение от Gepar Посмотреть сообщение
gameman, так вы ещё и поле тип добавили в каждый класс, мда ...
Почитайте что-то по с++ по полиморфизму, Страуструпа например.
Ну разве мне логично создавать по экземпляру класса для каждой вещи если их может быть более 5 млн (деревья, например)?
Я неправильно там написал кусок кода (он приведен для примера).

Вот что я имел в виду:
C++
1
2
3
4
for(int i = 0; i < count; i++){
if(obj[i].type = "door")      // Вот этих ифов я хочу избежать
Door_handler->Draw(obj[i].param);
}
Вот что у меня есть сейчас:

Объекты: Types - массив, хранящий параметры типов, их функции и указатель на класс-обработчик
C++
1
2
3
for(int i = 0; i < count; i++){
    Types[ obj[i].type ].Draw( Types[ obj[i].type ].HandlerPointer );   /* Статик-функция класса (указатель на нее), передаю ей указатель на класс, т.к. статик функи ничего не знают об экземплярах класса */
}
Добавлено через 2 минуты
Цитата Сообщение от silent_1991 Посмотреть сообщение
gameman, ифов не избежать, потому что какие-то действия нужно проделать только для объектов одних типов, какие-то - для других.
Я не принимаю во внимание обработку действий, типа если нажал, то то-то. Я рассматриваю конкретную вещь, например, активация предмета. В ней я пытаюсь избежать ифов, и это удалось, вопрос только какую технологию лучше использовать (у меня на уме только 2).
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
23.02.2012, 19:53     Группировка функций разных классов #11
Вот пример:
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
#include <iostream>
#include <string>
 
// Изначальня иерархия движка -------------------------------------------------
 
class Object
{
public:
    virtual void draw() const = 0;
};
 
class Creature : public Object
{
public:
    virtual void walk() const = 0;
};
 
class Light : public Object
{
public:
    virtual void shine() const = 0;
};
 
//-----------------------------------------------------------------------------
 
// А теперь конкретезируем движок ---------------------------------------------
 
class Human : public Creature
{
public:
    Human(const std::string name):
    m_name(name)
    {
    }
    
public:
    virtual void draw() const
    {
        std::cout << "I am a human. My name is " << m_name << std::endl;
    }
    
    virtual void walk() const
    {
        std::cout << "I can walk and I walk" << std::endl;
    }
    
private:
    std::string m_name;
};
 
class Lamp : public Light
{
public:
    Lamp(int illumination):
    m_illumination(illumination)
    {
    }
    
public:
    virtual void draw() const
    {
        std::cout << "Lamp..." << std::endl;
    }
    
    virtual void shine() const
    {
        std::cout << "Illumination + " << m_illumination << std::endl;
    }
    
private:
    int m_illumination;
};
 
int main()
{
    const size_t size = 5;
    
    Object *objects[size] =
    {
        new Human("John"),
        new Lamp(10),
        new Lamp(20),
        new Human("Jack"),
        new Lamp(4)
    };
    
    Human *human_ptr;
    Lamp *lamp_ptr;
    
    for (size_t i = 0; i < size; ++i)
    {
        objects[i]->draw();
        
        if ((human_ptr = dynamic_cast<Human *>(objects[i])) != 0)
            human_ptr->walk();
        else if ((lamp_ptr = dynamic_cast<Lamp *>(objects[i])) != 0)
            lamp_ptr->shine();
    }
    
    for (size_t i = 0; i < size; ++i)
        delete objects[i];
    
    return 0;
}
Здесь в цикле безусловно вызывается метод draw, поскольку он заведомо есть у всех классов. Но при необходимости происходит конкретизация при помощи условных операторов и динамического приведения типа.
gameman
0 / 0 / 0
Регистрация: 23.02.2012
Сообщений: 6
23.02.2012, 20:55  [ТС]     Группировка функций разных классов #12
Цитата Сообщение от silent_1991 Посмотреть сообщение
Вот пример:

Здесь в цикле безусловно вызывается метод draw, поскольку он заведомо есть у всех классов. Но при необходимости происходит конкретизация при помощи условных операторов и динамического приведения типа.
Спасибо за исходник, еще пара мыслей пришла в голову. Но ведь я же изначально сказал что есть похожий (такой же по принципу) способ =)
Хотел полюбопытствовать по поводу ваших мнений и других возможных вариантов. Ну ладно, всем большое спасибо за помощь! Если есть что еще интересное, то выкладывайте!
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.02.2012, 23:47     Группировка функций разных классов
Еще ссылки по теме:

Хранение в контейнере обьектов разных классов C++
Умножение матриц разных классов C++
C++ Передача структур разных классов

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

Или воспользуйтесь поиском по форуму:
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
23.02.2012, 23:47     Группировка функций разных классов #13
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
#include <iostream>
#include <vector>
#include <boost/bind.hpp>
#include <boost/function.hpp>
 
using namespace std;
 
class T1 {
public:
    void draw() {
        std::cout << "This is t1!\n";
    }
};
 
class T2 {
public:
    void another_draw() {
        std::cout << "This is t2!\n";
    }
};
 
int main()
{
 
    T1 t1;
    T2 t2;
 
    typedef boost::function<void (void)> function_type;
    std::vector<function_type> funcs;
 
    funcs.push_back(boost::bind(&T1::draw, &t1));
    funcs.push_back(boost::bind(&T2::another_draw, &t2));
 
    funcs[0]();
    funcs[1]();
 
    return 0;
}
This is t1!
This is t2!
Добавлено через 2 часа 34 минуты
кстати, почему-то сразу не подумал, но тебе, скорее всего, нужно что-то типа сигналов.
немного переделанный исходник.
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
#include <iostream>
#include <vector>
#include <boost/signal.hpp>
#include <boost/bind.hpp>
 
 
class T1 {
public:
    void draw() {
        std::cout << "This is t1!\n";
    }
};
 
class T2 {
public:
    void another_draw(bool fast) const {
        std::cout << "This is t2! " << (fast ? "fast" : "slooow") <<  "\n";
    }
};
 
void free_draw_func () {
    std::cout << "This is a free func \n";
}
 
int main()
{
 
    T1 t1;
    T2 t2;
 
    boost::signal<void (void)> funcs;
 
    funcs.connect(boost::bind(&T1::draw, &t1));
    funcs.connect(boost::bind(&T2::another_draw, &t2, true));
    funcs.connect(boost::bind(&T2::another_draw, &t2, false));
    funcs.connect(boost::bind(free_draw_func));
    funcs();
 
    return 0;
}
This is t1!
This is t2! fast
This is t2! slooow
This is a free func
Yandex
Объявления
23.02.2012, 23:47     Группировка функций разных классов
Ответ Создать тему
Опции темы

Текущее время: 03:38. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru