No faktycznie kiepsko to wytłumaczyłem o co mi chodzi..
Mamy klasy A, B oraz C
class A
{
int id;
};
class B
{
int id;
};
gdzie klasa C ma zawierać dwa kontenery wskaźników, osobny dla klasy A i B:
class C
{
std::vector < A* > A_ptr_container;
std::vector < B* > B_ptr_container;
};
// Opis klas jest oczywiście bardzo uproszczony, ale do dla Twojej wygody

Taka budowa bardzo mi odpowiada, ponieważ modyfikując osobno obiekty A i B nie muszę modyfikować ich reprezentacji w klasie C, ponieważ dzieje się to automatycznie poprzez wskaźnik. Tak samo na odwrót, jeżeli w klasie C chcę zmodyfikować atrybut obiektu klasy A lub B to odwołuję się do nich przez wskaźnik.
Proste.
Ale....
Jeżeli wywołam destruktor na obiekcie klasy A lub B, którego wskaźnik znajduje się w klasie C, to skąd obiekt klasy C ma wiedzieć czy takie wydarzenie miało miejsce? Co więcej skąd ma wiedzieć do której klasy należy dany obiekt i jakie ma ID (wprowadziłem założenie, że każdy obiekt ma być unikalny)?
No właśnie nie wie i gdybym chciał się odwołać przez wskaźnik znajdujący się w C do obiektu A lub B to wywołałbym wyciek pamięci i prawdopodobnie crash całego programu.
I tutaj właśnie z pomocą przychodzi mi Observer.
Ostatnio go lekko zmodyfikowałem i oto co udało mi się zrobić:
class Subject;
class Observer
{
public:
virtual bool Update(Subject * helper) = 0;
};
class Subject
{
protected:
std::list<Observer*> _observers;
public:
virtual void Attach(Observer* object)
{
_observers.push_back(object);
}
virtual void Detach(Observer* object)
{
_observers.remove(object);
}
virtual void Notify() = 0;
};
Jest to inna implementacja niż standardowa (czysto wirtualna metoda Notify()) co ma swoje ogromne zalety.
Zaimplementujmy więc Observer do klasy C i Subject do klasy A (B już pomijam bo to analogiczna sytuacja)
class A :public Subject
{
int id;
virtual void Notify() override
{
for (Observer *j : _observers)
j->Update(this);
}
};
Gdzie samą metodę notify() wywołuję w destruktorze klas A i B, by powiadomić klasę C o usunięciu obiektu, następnie metodą Update (w klasie implementującej Observera) usuwam obiekt z kontenerów, dzięki czemu zapobiegam odwołaniu sie do pustego/błędnego wskaźnika pozostałego po usunięciu obiektu A i B.
Samą metodę Attach na obiekcie klasy A lub B wywołuję w metodzie klasy C (już nie pisałem jest tutaj), która nazywa się add_A(A helper) lub add_B(B helper).
Wydaje mi się to proste i zrozumiałe. No bo chcę by obserwowanie obiektu klasy A zaczęło się w trakcie wrzucenia go do kontenera obiektu klasy C a zakończyło się z chwilą jego wyrzucenia stamtąd .
W obserwatorze natomiast muszę dodać pole w klasie odpowiadające za pomocnicze wskaźniki klas A i B.
class C :public Observer
{
std::vector < A* > A_ptr_container;
std::vector < B* > B_ptr_container;
A* A_helper;
B* B_helper;
virtual void Update(Subject * helper) override
{
if (helper == A_helper)
{
if (this->remove_A(helper->get_ID_A()));
return SUCCESS;
else
return ERROR;
}
else if (helper == B_helper)
{
if (this->remove_B(helper->get_ID_B()));
return SUCCESS;
else
return ERROR;
}
else
return ERROR;
};
};
I teraz muszę przekazywać albo wskaźnik do obiektu (tj to teraz zrobiłem) albo jak myślałem wcześniej, przekazywać dwa argumenty, tzn ID oraz unikalną dla klasy wartość static const jednoznacznie identyfikującą klasę.
Jednak po odwołaniu się do elementarnej wiedzy, dowiadujemy się, ze wskaźnik to są 4 bajty, więc rozwiązanie w dwoma argumentami jest cholernie nieoptymalne (całe piękno wskaźników w c++

).
No bo jak inaczej klasa C ma rozpoznać ID obiektu, który przestał powiadomienie i który trzeba usunąć z kontenera? Co więcej jak rozpoznać klasę tego obiektu a chciałem nadmienić, że w moim projekcie jest przewidziane miejsca dla właśnie dwóch klas, ale może być ich znacznie więcej i co wtedy?
Chcę wiedzieć co sądzisz o takim rozwiązaniu, czy jest ono optymalne czy jednak można zastosować jakąś inną technikę lub wzorzec.