Классы ссылающиеся друг на друга.
От: Andrewsha Россия http://andrewsha.com
Дата: 22.11.02 06:08
Оценка:
Всем привет!
Нужно сделать следующее:
Имеется несколько экземпляров класса А.
Класс А может собержать список экземпляров класса В.
Как зная В определить получить ссылку на А, который этот В держит в списке?

Проблема в том, что если класс А описывается в файле "А.h", а класс В в "В.h", то компилятор не позволяет чтобы они ссылались друг на друга.
Какие существуют методы, правильные пути решения данной задачи?
Re: Классы ссылающиеся друг на друга.
От: Bell Россия  
Дата: 22.11.02 06:36
Оценка: 4 (1)
Здравствуйте, Andrewsha, Вы писали:

A>Проблема в том, что если класс А описывается в файле "А.h", а класс В в "В.h", то компилятор не позволяет чтобы они ссылались друг на друга.


А как же forward declarations?


//a.h

class B;

class A
{
   ...

   B* pB;
};

//b.h

class A;

class B
{
   ...

   A* pA;
};
Любите книгу — источник знаний (с) М.Горький
Re[2]: Классы ссылающиеся друг на друга.
От: Andrewsha Россия http://andrewsha.com
Дата: 22.11.02 08:18
Оценка:
Здравствуйте, Bell, Вы писали:

B>А как же forward declarations?

Ну чайник я, чайник
Все классно работает . Но в реале мне надо:
//a.h

class A
{
   ...
   BB* pB;
};
typedef A AA;

//b.h

class B
{
   ...
   AA* pA;
};
typedef B BB;


Так не прокатывает, потому что forward declaration для классов а ВВ или АА не классы...Как быть? Видимо надо typedef-ить в модулях, где собираюсь использовать новый тип. Просто тут не очень красиво получается, если в нескольких модулях хочу использовать, то придется typedef-ить несколько раз.
Re: Классы ссылающиеся друг на друга.
От: Аноним  
Дата: 22.11.02 09:39
Оценка:
Здравствуйте, Andrewsha, Вы писали:

A>Всем привет!

A>Нужно сделать следующее:
A>Имеется несколько экземпляров класса А.
A>Класс А может собержать список экземпляров класса В.
A>Как зная В определить получить ссылку на А, который этот В держит в списке?

A>Проблема в том, что если класс А описывается в файле "А.h", а класс В в "В.h", то компилятор не позволяет чтобы они ссылались друг на друга.

A>Какие существуют методы, правильные пути решения данной задачи?

А ЗАЧЕМ ЭТО ВООБЩЕ НАДО?
Re[2]: Классы ссылающиеся друг на друга.
От: Andrewsha Россия http://andrewsha.com
Дата: 22.11.02 09:44
Оценка:
А>А ЗАЧЕМ ЭТО ВООБЩЕ НАДО?
Чтобы зная В быстро получить ссылку на А, который этот В держит в списке.
Re[3]: Классы ссылающиеся друг на друга.
От: Аноним  
Дата: 22.11.02 09:51
Оценка:
Здравствуйте, Andrewsha, Вы писали:

А>>А ЗАЧЕМ ЭТО ВООБЩЕ НАДО?

A>Чтобы зная В быстро получить ссылку на А, который этот В держит в списке.

Я это понял, просто мне интересно знать с точки зрения проэктирования

class B
{
public:
B();
~B();
};

class A
{
private:
list<B> list_of_B;
public:
A();
...
~A();
}

Зачем list_of_B знать об A. Помоему с точки зрения инкапсуляции данных даже это не совсем правильно, или все же что то я не правильно понял...
Re[3]: Классы ссылающиеся друг на друга.
От: Алекс Россия http://wise-orm.com
Дата: 22.11.02 09:52
Оценка: 4 (1)
Здравствуйте, Andrewsha, Вы писали:

А>>А ЗАЧЕМ ЭТО ВООБЩЕ НАДО?

A>Чтобы зная В быстро получить ссылку на А, который этот В держит в списке.

И почему это не может быть глобальная функция-друг обоих классов?

Кстати на счет списка. Структура данных выбирается исходя из контекста ее использования. Если у тебя часто происходит удаление и вставка, а поиск или другой какой запрос — редко, выбирай однозначно list. Если чаще приходится искать — массив (vector), а лучше дерево какое-нибудь. Я не большой знаток STL и всяких boost'ов, но наверняка там что-либо подобное имеется.

З.Ы. Так как ты новичок, настоятельно рекомендую ознакомится с правилами и системой оценок на сайте. Если человек тебе помог, то грех его не поблогадарить, хотя бы словами. Хотя словами иногда даже приятнее.
Re[4]: Классы ссылающиеся друг на друга.
От: Andrewsha Россия http://andrewsha.com
Дата: 22.11.02 10:00
Оценка:
А> Я это понял, просто мне интересно знать с точки зрения проэктирования

А>class B

А>{
А>public:
А>B();
А>~B();
А>};

А>class A

А>{
А>private:
А>list<B> list_of_B;
А>public:
А>A();
А>...
А>~A();
А>}

А>Зачем list_of_B знать об A. Помоему с точки зрения инкапсуляции данных даже это не совсем правильно, или все же что то я не правильно понял...

Да, все правильно изложено. Только теперь допустим, что известен В, как получить А, у которого этот В в списке? Или ты имеешь ввиду ситуацию, когда это может понадобиться? Мол изначально что-то неправильно спроектированно, поскольку возникла такая необходимость...?
Re[4]: Классы ссылающиеся друг на друга.
От: Andrewsha Россия http://andrewsha.com
Дата: 22.11.02 10:03
Оценка:
А>И почему это не может быть глобальная функция-друг обоих классов?
Надо посмотреть че это за зверь Просто щас не понимаю о чем речь

А>Кстати на счет списка. Структура данных выбирается исходя из контекста ее использования. Если у тебя часто происходит удаление и вставка, а поиск или другой какой запрос — редко, выбирай однозначно list. Если чаще приходится искать — массив (vector), а лучше дерево какое-нибудь. Я не большой знаток STL и всяких boost'ов, но наверняка там что-либо подобное имеется.



А>З.Ы. Так как ты новичок, настоятельно рекомендую ознакомится с правилами и системой оценок на сайте. Если человек тебе помог, то грех его не поблогадарить, хотя бы словами. Хотя словами иногда даже приятнее.

Реальное спасибо за оперативные ответы!!!
Re[5]: Классы ссылающиеся друг на друга.
От: Аноним  
Дата: 22.11.02 10:04
Оценка:
Здравствуйте, Andrewsha, Вы писали:

А>> Я это понял, просто мне интересно знать с точки зрения проэктирования


А>>class B

А>>{
А>>public:
А>>B();
А>>~B();
А>>};

А>>class A

А>>{
А>>private:
А>>list<B> list_of_B;
А>>public:
А>>A();
А>>...
А>>~A();
А>>}

А>>Зачем list_of_B знать об A. Помоему с точки зрения инкапсуляции данных даже это не совсем правильно, или все же что то я не правильно понял...

A>Да, все правильно изложено. Только теперь допустим, что известен В, как получить А, у которого этот В в списке? Или ты имеешь ввиду ситуацию, когда это может понадобиться?

ДА

Мол изначально что-то неправильно спроектированно, поскольку возникла такая необходимость...?

Совершенно верно...
Re[5]: Классы ссылающиеся друг на друга.
От: Анатолий Широков СССР  
Дата: 22.11.02 10:30
Оценка:
A>Только теперь допустим, что известен В, как получить А, у которого этот В в списке?


// header.h
class A; 
class B 
{ 
public: 
   B(A* owner) : _owner( owner ) {}
   ~B() {} 

   void use_owner();
private:
   A *_owner;
}; 

class A 
{ 
public: 
   A(); 
   ~A(); 
private: 
   list<B> list_of_B; 
};
// header.cpp
#include "header.h"

void B::use_owner()
{
  // теперь нам доспупно определение интерфейса
  _owner->...;
}
Re[5]: Классы ссылающиеся друг на друга.
От: Алекс Россия http://wise-orm.com
Дата: 22.11.02 10:30
Оценка: 4 (1)
Здравствуйте, Andrewsha, Вы писали:

А>>И почему это не может быть глобальная функция-друг обоих классов?

A>Надо посмотреть че это за зверь Просто щас не понимаю о чем речь

[]

Можно поступить двумя способами

class A;
class B
{
public:
    bool is_b_in_a(A& a);
};

class A
{
protected:
    list<B*> list_of_b;
public:
    void Add(B* b)
    {
        list_of_b.push_back(b);
    }
    bool is_b_in_list(B* b)
    {
        list<B*>::iterator it = find(list_of_b.begin(),list_of_b.end(),b);
        return it != list_of_b.end();
    }

    friend bool B::is_b_in_a(A&);
};

bool B::is_b_in_a(A& a)
{
    list<B*>::iterator it = find(a.list_of_b.begin(),a.list_of_b.end(),this);
    return it != a.list_of_b.end();
}

int main()
{    
    B b1,b2,b3,b4;
    A a1;
    a1.Add(&b1);
    a1.Add(&b2);
    a1.Add(&b3);
    cout << a1.is_b_in_list(&b2) << endl;
    cout << b4.is_b_in_a(a1) << endl;

    getch();
    return 0;
}


Т.е. либо из B проверять принадлежность к А, либо из А проверять принадлежность к нему В. Пример для vector'а приктически отличатся ничем не будет.
Re[6]: Классы ссылающиеся друг на друга.
От: Valcomer http://valsoftnet.narod.ru
Дата: 22.11.02 10:31
Оценка: -1
Здравствуйте, Анатолий Широков, Вы писали:

Избыточное цитирование удалено модератором. -- ПК

А зачем так извращаться?
Re[7]: Классы ссылающиеся друг на друга.
От: Анатолий Широков СССР  
Дата: 22.11.02 10:34
Оценка:
Ты о чем?
Так например постоена саморегистрация wxWindow в родителе.
Re[8]: Классы ссылающиеся друг на друга.
От: Valcomer http://valsoftnet.narod.ru
Дата: 22.11.02 10:38
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Ты о чем?

АШ>Так например постоена саморегистрация wxWindow в родителе.

Саморегистрацию можна сделать и так например:

class Window
{
private:
static list<Window*> list_of_ptr_window;
public:
Window();
...
static void Show();
...
~Window();
}
Re[9]: Классы ссылающиеся друг на друга.
От: Анатолий Широков СССР  
Дата: 22.11.02 10:40
Оценка:
А теперь будь добер реализацию ClientToScreen для чайда на бис
Re[10]: Классы ссылающиеся друг на друга.
От: Valcomer http://valsoftnet.narod.ru
Дата: 22.11.02 10:44
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>А теперь будь добер реализацию ClientToScreen для чайда на бис


Не нужно все приувеличивать, это просто пример....
Re[6]: Классы ссылающиеся друг на друга.
От: Andrewsha Россия http://andrewsha.com
Дата: 22.11.02 10:56
Оценка:
А>>>И почему это не может быть глобальная функция-друг обоих классов?
[]
Спасибо за наглядный пример!
А>Т.е. либо из B проверять принадлежность к А, либо из А проверять принадлежность к нему В. Пример для vector'а приктически отличатся ничем не будет.
Понятно, толкьо ведь можно в В просто хранить указатель на А, который этот В держит в списке.

К вопросу о typedef:
//a.h
class A
{   ...
   BB* pB;
};
typedef A AA;

//b.h
class B
{   ...
   AA* pA;
};
typedef B BB;


Так не прокатывает, потому что forward declaration для классов, а ВВ или АА не классы...Как быть? Видимо надо typedef-ить в модулях, где собираюсь использовать новый тип. Просто тут не очень красиво получается, если в нескольких модулях хочу использовать, то придется typedef-ить несколько раз.
Re[11]: Классы ссылающиеся друг на друга.
От: Анатолий Широков СССР  
Дата: 22.11.02 10:58
Оценка: -1
У меня был тоже пример. Хорошо, вот пример из моей практики:


class Object
{
public:
   virtual ~Object() {}
   virtual void draw(Context &) = 0;
};

// корабль
//
class Ship : public Object
{
public:
};

class Order;

// позиция в ордере - посредник по сути между ордером и кораблем
//
class OrderPosition : public Ship
{
public:
   OrderPosition(Order* order, double distance, double couse_angle)
      : _owner(order), _ship(0), _distance(distance), _cours_eangle(0) 
   {
   }

   void draw(Context &c)
   {
       _ship->draw(c);
   }

private:
   Order* _owner; // он мне нужен, поскольку позиция не обладает информацией о тот кто является уравнителем, какой целевой курс - это информация более высокого уровня
   Ship* _ship;
   double _distance;
   double _course_angle;
};

// ордер - группа кораблей (каждый корабль имеет строго регламентированный порядок)
//
class Order : public Object
{
public:
   ... 
};


К чему это я все? — много задач хороших и разных
Re[7]: Классы ссылающиеся друг на друга.
От: Алекс Россия http://wise-orm.com
Дата: 22.11.02 11:03
Оценка:
Здравствуйте, Andrewsha, Вы писали:

[]

A>Так не прокатывает, потому что forward declaration для классов, а ВВ или АА не классы...Как быть? Видимо надо typedef-ить в модулях, где собираюсь использовать новый тип. Просто тут не очень красиво получается, если в нескольких модулях хочу использовать, то придется typedef-ить несколько раз.


Зачем несколько раз?
//b.h
class A;
typedef A AAA;
class B{
//use AAA
};

class B;
typedef B BBB;
//a.h
class A{
//use BBB
};
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.