Собсно сабж: есть наборы объектов двух типов. Нужно связать их между собой, чтобы по связям можно было вытащить соответственные наборы объектов. В базах данных обычно используют создание дополнительной связующей сущности. Как это грамотно реализовать в стиле ООП?
Здравствуйте, Павел Сумароков, Вы писали:
ПС>Создать третий класс агрегирующий объекты первых двух типов. Если нужно отношение многие ко многим, то новый класс будет содержать два списка. Один ко многим — ссылка и список, и т.д.
Можно ещё объект связи интрузивно включить в связываемые объекты:
#include <iostream>
#include <boost/intrusive/list.hpp>
using namespace boost::intrusive;
struct foo;
struct bar;
typedef list_base_hook< tag<foo> > foo_hook;
typedef list_base_hook< tag<bar> > bar_hook;
// тип связи
struct foo_bar : foo_hook, bar_hook
{
foo_bar(foo& f, bar& b);
foo& f_;
bar& b_;
void print();
void release();
};
struct foo
{
foo() { static int id = 0; id_ = id++; }
~foo() { while(!bar_.empty()) bar_.front().release(); }
int id_;
list<foo_bar, base_hook<foo_hook> > bar_;
void print() { std::for_each(bar_.begin(), bar_.end(), std::mem_fun_ref(&foo_bar::print)); }
};
struct bar
{
bar() { static int id = 0; id_ = id++; }
~bar() { while(!foo_.empty()) foo_.front().release(); }
int id_;
list<foo_bar, base_hook<bar_hook> > foo_;
void print() { std::for_each(foo_.begin(), foo_.end(), std::mem_fun_ref(&foo_bar::print)); }
};
foo_bar::foo_bar(foo& f, bar& b)
: f_(f)
, b_(b)
{
f.bar_.push_back(*this);
b.foo_.push_back(*this);
}
void foo_bar::print() { std::cout << "foo[" << f_.id_ << "] -> bar[" << b_.id_ << "]" << std::endl; }
void foo_bar::release() { f_.bar_.erase(f_.bar_.iterator_to(*this)); b_.foo_.erase(b_.foo_.iterator_to(*this)); delete this; }
int main()
{
int i;
foo f[5];
bar b[5];
for(i=0; i<5; ++i)
{
new foo_bar(f[i], b[i]);
new foo_bar(f[i], b[(i==4)?0:i+1]);
}
std::cout << "foo links:" <<std::endl;
std::for_each(&f[0], &f[5], std::mem_fun_ref(&foo::print));
std::cout << "bar links:" <<std::endl;
std::for_each(&b[0], &b[5], std::mem_fun_ref(&bar::print));
return 0;
}