Russian Qt Forum

Программирование => С/C++ => Тема начата: ieroglif от Август 05, 2009, 21:55



Название: проблема с архитектурой классов(как сделать forward declaration на метод класса)
Отправлено: ieroglif от Август 05, 2009, 21:55
имеется:
класс Х.
классов Х может быть много и они могут быть в любом месте проекта (понятное дело, что в относительно любом), могут быть подобъектами самих же себя (т.е. в объекте А класса Х создаётся свойством объект Б тоже унаследованный от класса Х причём не обязательно "из первых рук" [т.е. есть класс Й, который наследуется от Х, и Б - просто реализует Й]).

Все объекты от класса Х имеет некое свойство П, по которому они время от времени опрашиваются и далее по необходимости с ними что-то делается.
Неумолимая логика подсказывает создание класса У (для полноты картины), и тотальная регистрация всем объектам класса Х (и его наследников) в этом объекте У, которые сможет опрашивать их свойство П и решать - надо что-то делать или не надо.

Но при этом получается следующая фигня.

Для регистрации объектов Х и их проверки объект У должен о них знать, а следовательно
#include "x.h" (внутри y.h )
но что бы объекты Х смогли зарегиться, то хочется им всем передать ссылочку на У, что бы они смогли сделать
У->а_вот_и_я(*я);
что автоматически порождает за собой
#include "y.h" (внутри x.h )
что автоматически порождает за собой недоумённые глаза компилятора, мои ругательства и бычки в пепельнице.
как первое, так и второе (считаем с ноля) не особо нравится людям с которыми я живу (хоть они и привыкли) и вообще накаляет обстановку в доме.

После некоторого раздумья пришла в голову мысль о том, что бы объекты класса Х выдавали сигнал
эмит А_вот_и_я(*Х)
а уж внутри У разобрать их не проблема, но тогда получается, что мне надо соединять ВСЕ мои объекты класса Х с У, что порождает за собой недоумение - у меня же они могут вполне создаваться и подобъектами, и вообще очень много где - это что ж получается, надо протаскивать через кучу цепочек созданных объектов и подобъектов сигналы вложенности?
это мне кажется тоже каким-то бредом.

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


Название: Re: проблема с архитектурой классов
Отправлено: BRE от Август 05, 2009, 22:01
Но при этом получается следующая фигня.

Для регистрации объектов Х и их проверки объект У должен о них знать, а следовательно
#include "x.h" (внутри y.h )
но что бы объекты Х смогли зарегиться, то хочется им всем передать ссылочку на У, что бы они смогли сделать
У->а_вот_и_я(*я);
что автоматически порождает за собой
#include "y.h" (внутри x.h )
Почитай на тему Forward Declaration.  ;)


Название: Re: проблема с архитектурой классов
Отправлено: ieroglif от Август 05, 2009, 22:34
Но при этом получается следующая фигня.

Для регистрации объектов Х и их проверки объект У должен о них знать, а следовательно
#include "x.h" (внутри y.h )
но что бы объекты Х смогли зарегиться, то хочется им всем передать ссылочку на У, что бы они смогли сделать
У->а_вот_и_я(*я);
что автоматически порождает за собой
#include "y.h" (внутри x.h )
Почитай на тему Forward Declaration.  ;)

хм..
мысль понял.
не совсем понял как я буду вызывать функционал (то бишь функцию У->а_вот_и_я(); ) этого самого заранее продекларируемого класса.
неужто компилятор такой умный и будет подтягивать его автоматом?

ну и совсем вопрос для полноты картины понимания.
получается, что в классе Х я объявляю
Код:
class У;

class X {
....
protected //что бы потомкам пришло тоже
    static Y *y;
}

Y* X::y; //если я правильно понял документацию, то статические члены должны быть определены отдельно.

// в x.cpp
X::X() {
    y->register_me(this);   // гарантированно, что объект У создаётся раньше чем любой из реализующих Х
}

после того, как объект У был создан я прописываю
Код:
Y myY;
X::y = &myY;
и радуюсь счастливой и долгой жизни? =)


Название: Re: проблема с архитектурой классов
Отправлено: BRE от Август 05, 2009, 22:49
не совсем понял как я буду вызывать функционал (то бишь функцию У->а_вот_и_я(); ) этого самого заранее продекларируемого класса.
неужто компилятор такой умный и будет подтягивать его автоматом?
В .h ты его декларируешь, а в .cpp ты его подключаешь #include и пользуешся его функционалом.

ну и совсем вопрос для полноты картины понимания.
Ну а тут есть широкое поле для творчества...  ;)
Можно в классе X сделать статический список в который помещать все созданные объекты, можно указатель/ссылку на объект Y передовать в конструктор X, можно Y сделать singleton'ом... Много чего можно придумать.  :)


Название: Re: проблема с архитектурой классов(как сделать forward declaration на метод класса)
Отправлено: ieroglif от Август 05, 2009, 23:01
BRE, спасибо огромное =)
предварительным декларированием и подключением h файла в cpp база заработала =)
сейчас разбираюсь со статикой, ибо она мне кажется логичнее всего - объектов от класса Х у меня может быть полно и разбросаны они могут быть по коду не слабо, так что искать каждый что бы ему через непонятные цепочки вложенности передать указатель на У мне кажется неправильным, а вот сделать указатель на У статическим, выставив его один раз при создании этого У - это мне кажется логичным =)
тогда как только я создаю объект как-то наследованный от Х - он автоматом регистрится а я об этом уже и не думаю =)
удобно и приятно.
в общем, разбираюсь со статикой =)
если есть совет или ман приятный для мозговарения - буду рад =)


Название: Re: проблема с архитектурой классов(как сделать forward declaration на метод класса)
Отправлено: Alex Custov от Август 06, 2009, 00:24
Используй синглетоны.

Код:
// h
class Y
{
    public:
        Y();
        ~Y();

        Y* instance();

    private:
        static Y *m_instance;
};

inline
Y* Y::instance()
{
    return m_instance;
}

// cpp
Y::Y * m_instance = 0;

Y::Y()
{
    if(!m_instance)
        m_instance = this;
    ...
}

Y::~Y()
{
    m_instance = 0;
}

Код:
void X::somemethod()
{
    Y::instance()->doSomething();
}


Название: Re: проблема с архитектурой классов(как сделать forward declaration на метод класса)
Отправлено: Авварон от Август 06, 2009, 11:47
2 автор:
По-моему вы неправильно рассматриваете объекто-ориентированную модель. В вашем случае на мой взгляд механизм регистрации лучше перенести в класс Y - через метод register(X*).
По хорошему, Х ничего не должны знать об классе, который их мониторит. Возможно потребуется объявить класс Y другом внутри класса Х, но это будет проще и логичней, чем работать с перекрестными ссылками