Ответ ФА. - хорошее начало. Однако это не решает проблему наличия нескольких владельцев одного типа. Одно из решений заключается в том, чтобы уведомитель сохранял список владельцев вместо одного. Вот быстрая реализация, чтобы показать идею:
template <typename Owner, typename Owned>
class Notifier
{
protected:
Notifier()
{}
// Constructor taking a single owner
Notifier(Owner & o)
{
owners.push_back(&o);
}
// Constructor taking a range of owners
template <typename InputIterator>
Notifier(InputIterator firstOwner, InputIterator lastOwner)
: owners(firstOwner, lastOwner) {}
~Notifier()
{
OwnerList::const_iterator it = owners.begin();
OwnerList::const_iterator end = owners.end();
for ( ; it != end ; ++it)
{
(*it)->notify(static_cast<Owned*>(this));
}
}
// Method for adding a new owner
void addOwner(Owner & o)
{
owners.push_back(&o);
}
private:
typedef std::vector<Owner *> OwnerList;
OwnerList owners;
};
Вы можете использовать это следующим образом:
class Owner;
class Owned : public Notifier<Owner, Owned>
{
typedef Notifier<Owner, Owned> base;
//Some possible constructors:
Owned(Owner & o) : base(o) { }
Owned(Owner & o1, Owner & o2)
{
base::addOwner(o1); //qualified call of base::addOwner
base::addOwner(o2); //in case there are other bases
}
Owned(std::list<Owner*> lo) : base(lo.begin(), lo.end()) { }
};
В случае, когда у вас много разных типов владельцев, это решение может стать довольно сложным в использовании. В этом случае вам, возможно, захочется взглянуть на библиотеки повышения метапрограммирования ( MPL , Fusion ), с помощью которых вы можете получить код, позволяющий вам делать такие вещи:
class Owned : public Notifier<Owned, OwnerType1, OwnerType1, OwnerType2>
{
Owned(OwnerType1 & o1, OwnerType1 & o2, OwnerType2 & o3)
: base(o1,o2,o3)
};
Однако реализация этого решения будет немного дольше, чем предыдущая.