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

Можно ли из класса родителя просигналить всем потомкам? - C++

Войти
Регистрация
Восстановить пароль
 
babkaVkedah
Заблокирован
11.07.2013, 10:18     Можно ли из класса родителя просигналить всем потомкам? #1
Если есть базовый класс "X" и несколько его потомков "A", "B" и "C", можно ли как то через объект базового класса сообщить всем созданным потомкам выполнить какую - то функцию?

Например:
C++
1
2
3
4
5
6
7
8
9
10
X* x = new X;
A* a = new A;
B* b = new B;
C* c = new C;
 
//хочу как - то вызвать функцию, виртуальную наверно, 
//в классе "X", чтоб она вызвалась во всех потомках
 
x->DoWork();
//и после этого во всех классах потомках должна вызваться такая же функция
... ???
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.07.2013, 10:18     Можно ли из класса родителя просигналить всем потомкам?
Посмотрите здесь:

C++ Доступ из вложенного класса к членам "родителя"
Можно ли прятать методы класса в пространство имен? C++
C++ Подсказка ко всем методам и ко всем их параметрам
Можно ли как-то в дочернем классе получить указатель родителя? C++
C++ Лишнее удаление родителя при создании класса наследника
C++ Можно ли сохранить данные класса в файл
Нужно из класса наследника передать параметры в класс родителя C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт С++
 Аватар для ForEveR
7955 / 4717 / 318
Регистрация: 24.06.2010
Сообщений: 10,525
Завершенные тесты: 3
11.07.2013, 10:22     Можно ли из класса родителя просигналить всем потомкам? #2
babkaVkedah, Возможно. Сохранять все инстансы в базовом классе. Но это откровенно говоря изврат.
Ilot
Модератор
Эксперт С++
1778 / 1153 / 223
Регистрация: 16.05.2013
Сообщений: 3,042
Записей в блоге: 5
Завершенные тесты: 1
11.07.2013, 10:35     Можно ли из класса родителя просигналить всем потомкам? #3
babkaVkedah, не думаю, что это возможно по причине того что будет необходимо выполнить метод для всех наследников класса. А теперь вопрос: существеут ли в С++ способ/метод по умолчанию учета всех созданных объектов класса A, B, C? Насколько мне известно нет. Поля класса инициализируются при определении объектов и связи с базовым классом в последствии не несут. Что бы вызвать выполнение методов наследников базового класса необходимо ссылыться на каждый созданный объкт. Ну... примерно так.

Единственный вариант который мне приходит на ум это создание в базовом классе массива указателей на создаваемые объекты. Таким образом создавая новый объект вы автоматически сохраняете на него ссылку. Далее при вызове вашего метода он(метод) считывает адрес созданных объектов и вызывает их методы. Все это происходит в цикле по всему массиву указателей до встречи нулевого указателя. Как это реализовать это отдельный вопрос, но думаю суть ясна. Чем-то напоминат списки.
babkaVkedah
Заблокирован
11.07.2013, 10:53  [ТС]     Можно ли из класса родителя просигналить всем потомкам? #4
У меня есть ещё вариант, задействовать Qt.
В базовом, да и во всех остальных, создать два метода Get и Set (set - signal, get - slot), чтоб можно было бы передавать что - то, например через строку джейсоновской натацией и получать что - то. Во всех классах потомках вызывать два connect, присоединяя Set потомка к Get родителя. А в базовом классе в слоте Get делать emit Set, чтоб при каждом получение Get из любого потомка, он испускал сигнал ко всем потомкам, ну как - то так
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
11.07.2013, 13:58     Можно ли из класса родителя просигналить всем потомкам? #5
Примитивный вариант
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
#include <iostream>
#include <string>
#include <vector>
 
class Base
{
public:
    static void Signal()
    {
        for (std::vector<Base*>::iterator it = _instances.begin() ; it != _instances.end(); ++it)
        {
            (*it)->DoWork();
        }
    }
 
    virtual ~Base()
    {
        for (std::vector<Base*>::iterator it = _instances.begin() ; it != _instances.end(); ++it)
        {
            if (*it == this)
            {
                _instances.erase(it);
                break;
            }
        }
 
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
    Base(std::string const& name)
    {
        _name = name;
        _instances.push_back(this);
 
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
    virtual void DoWork()
    {
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
 
private:
    static std::vector<Base*> _instances;
 
protected:
    std::string _name;
};
std::vector<Base*> Base::_instances;
 
class DerivedA : public Base
{
public:
    virtual ~DerivedA()
    {
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
    DerivedA(std::string name) : Base(name)
    {
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
    void DoWork()
    {
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
};
 
class Derived2A : public DerivedA
{
public:
    virtual ~Derived2A()
    {
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
    Derived2A(std::string name) : DerivedA(name)
    {
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
    void DoWork()
    {
        std::cerr << "Calling method \'" << __FUNCTION__ << "\' for object \'" << _name << "\'\n";
    }
};
 
int main()
{
    Base* base = new Base("base");
    DerivedA derivedA("derivedA");
    DerivedA* derived2A = new Derived2A("deriveda2A");
 
    Base::Signal();
 
    delete derived2A;
    delete base;
    return 0;
}
Кудаив
329 / 406 / 24
Регистрация: 27.05.2012
Сообщений: 1,164
Завершенные тесты: 2
11.07.2013, 19:50     Можно ли из класса родителя просигналить всем потомкам? #6
паттерн проектирования "наблюдатель", не?
на Qt куда элегантнее будет
alsav22
5284 / 4803 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
12.07.2013, 05:03     Можно ли из класса родителя просигналить всем потомкам? #7
Цитата Сообщение от babkaVkedah Посмотреть сообщение
x->DoWork();
//и после этого во всех классах потомках должна вызваться такая же функция
Что мешает в этом месте вызвать эти функции?
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
12.07.2013, 07:04     Можно ли из класса родителя просигналить всем потомкам? #8
Цитата Сообщение от Кудаив Посмотреть сообщение
паттерн проектирования "наблюдатель", не?
В общем, да.
Цитата Сообщение от Кудаив Посмотреть сообщение
на Qt куда элегантнее будет
Не знаком, не знаю.
Цитата Сообщение от alsav22 Посмотреть сообщение
Что мешает в этом месте вызвать эти функции?
Наверное то, что не ведется yчет всех объектов-потомков.
babkaVkedah
Заблокирован
12.07.2013, 08:14  [ТС]     Можно ли из класса родителя просигналить всем потомкам? #9
Цитата Сообщение от nxtech Посмотреть сообщение
Наверное то, что не ведется yчет всех объектов-потомков.
Конечно не ведётся, иначе какая же это автоматизация Думаю, лучший вариант - тот, который я сам предложил через Qt
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
12.07.2013, 09:32     Можно ли из класса родителя просигналить всем потомкам? #10
Ну, если Qt позволяет меньше писать кода, то, можно этим воспользоваться.
Но учет все-равно должен как-то где-то вестись, пусть это и скрыто от нас (connect как бы намекает).
babkaVkedah
Заблокирован
12.07.2013, 10:19  [ТС]     Можно ли из класса родителя просигналить всем потомкам? #11
Цитата Сообщение от nxtech Посмотреть сообщение
Но учет все-равно должен как-то где-то вестись, пусть это и скрыто от нас
В том то и дело, что не надо
Фишка в том, что как я и говорил, в базовом классе делаешь SET и GET, а коннектишся к ним только в дочерних классах. Тоесть в дочернем классе надо просто иметь указатель на базовый и делать два коннекта.
Кстате, как лучше получить указатель на базовый класс в дочерних?
Как известно this, возвращает указатель на данный класс, может есть какая - то конструкция для получения указателя родителя? Может он так же как и для this где - то не явно храниться? Или же надо в базовом классе передавать указатель на самого себя в конструкторе?
nxtech
77 / 59 / 2
Регистрация: 26.06.2013
Сообщений: 198
12.07.2013, 10:59     Можно ли из класса родителя просигналить всем потомкам? #12
Цитата Сообщение от babkaVkedah Посмотреть сообщение
В том то и дело, что не надо
Ну, может я не совсем понятно и корректно выражаюсь. Но вот понятно, что объект генерирующий сигнал, не обязан ничего знать о получателях сигнала (более того, получателей может и не быть вовсе) и, соответственно, получатели не обязаны ничего знать об объекте генерирующем сигнал.
Но сама внутренняя реализация механизма сигналов-слотов должна же как-то знать какие адреса (функции) вызывать при поступлении сигнала.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.07.2013, 22:10     Можно ли из класса родителя просигналить всем потомкам?
Еще ссылки по теме:

Сериализация custom обьектов, которые имеют общего родителя и поле другого класса C++
Можно ли использовать объекты одного класса в другом? C++
C++ Создание категорий меню в private класса родителя
C++ Изменения названия переменной класса родителя в классе наследнике
Переопределение переменной класса-родителя C++

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

Или воспользуйтесь поиском по форуму:
soican
49 / 23 / 1
Регистрация: 16.11.2011
Сообщений: 329
Записей в блоге: 5
12.07.2013, 22:10     Можно ли из класса родителя просигналить всем потомкам? #13
nxtech, кладу в избранное, как пособие по наследованию)
Yandex
Объявления
12.07.2013, 22:10     Можно ли из класса родителя просигналить всем потомкам?
Ответ Создать тему
Опции темы

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