Autor Wątek: Zawieranie się obiektów  (Przeczytany 10331 razy)

Offline Xion

  • Redaktor
    • xion.log

# Sierpień 10, 2007, 21:16:59
A po co aż makro? Można napisać zwyczajną funkcję. Tak czy siak to faktycznie ciekawy szczegół, o którym wcześniej nie pomyślałem :) Myślę, że to można by częściowo obejść tworząc w kontenerze kolejkę obiektów oczekujących na dodanie. W momencie użycia kontenera do jakiegoś celu, który wymaga dostępu do obiektów, byłyby one faktycznie dodawane do niego z wykonaniem tych operacji, które w konstruktorze mogłyby się wywalać.

Wada: Nadmierne skomplikowanie i przeniesienie części operacji tam, gdzie nie bardzo się ich spodziewamy.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline krajek

  • Użytkownik

# Sierpień 11, 2007, 12:12:08
A po co aż makro? Można napisać zwyczajną funkcję.
To odchodzi od głównego tematu ale..
Próbowałem jakoś rozsądnie zrobić zamiast makra funkcje, ale mi sie nie udało. Metoda CtorHack nie jest wirtualna ,więc trzeba znać typ KonkretnejEntity,  żeby ją wywołać. Przy czym założyłem sobie, że klas Entity i Kontener nie zmieniam.
Jeśli możesz to pokaż jak wykonać taką funkcję.

Offline Xion

  • Redaktor
    • xion.log

# Sierpień 11, 2007, 13:37:19
Niby dlaczego funkcja CtorHack miałaby być wirtualna? Przecież w swoim makrze przy jej wywoływaniu też nie korzystasz z wiedzy, jakiego konkretnego typu obiekt utworzyłem, bo posługujesz się wskaźnikiem na bazowe Entity.

Rzeczona funkcja mogłaby wyglądać tak:
template <class _Concrete> Entity* Create(Kontener& k)
{ Entity* e = new _Concrete(&k); e->CtorHack(); return e; }

Offline krajek

  • Użytkownik

# Sierpień 11, 2007, 18:46:21
Xion : już po tym jak się ciebie zapytałem, rozwiązanie z wykorzystaniem szablonów przyszlo mi do głowy ... jak myłem zęby  ;D.
Jakąś miałem zaćme, że na to nie wpadłem.

Offline Reg

  • Administrator
    • Adam Sawicki - Home Page

# Sierpień 15, 2007, 16:14:58
Nowe wieści z pierwszej linii frontu. Wiedziałem że ten mój CtorHack to brzydki hack, ale nie wiedziałem co na to poradzić. Aż do przed chwilą, kiedy to leżąc sobie bez celu wpadłem na lepszy pomysł. Otóż promień sfery otaczającej czy tam prostopadłościan otaczający AABB albo cokolwiek jest, podobnie jak pozycja, przypisany w konstruktorze klasy bazowej Entity jako jakaś wartość domyślna. Jest pamiętany w polu. Nie ma do niego metody wirtualnej. Dzięki temu encja dodawać do kontenera może się w konstruktorze, nie musi być CtorHack, kontener może odpytać ją przy tym o jej AABB i wszystko działa. Potem klasa pochodna może w dowolnym miejscu, nawet w swoim konstruktorze, wywołać SetAABB klasy bazowej, co spowoduje aktualizację pola pamiętającego ten AABB oraz prześle do kontenera sygnał, żeby odpytać encję o jej pozycję, AABB i inne parametry i na tej podstawie, jeśli trzeba, uaktualnić jej położenie w drzewie podziału przestrzeni. Trochę zamotałem, ale jak kogoś to interesuje to może zrozumie :) Skodziłem to i działa.

Offline klosio.neostr...

  • Użytkownik
    • Moje Stare Gierki

# Sierpień 18, 2007, 22:27:07
Co do pierwszego posta, to w swoim GUI zastosowałem rozwiązanie nr2, z możliwością włączenia nr3. Decyduje o tym zmiena booliczna w menedżerze GUI, który jest jednostanem :) Działa znakomicie. Domyślnie nr3 jest wyłączone, choć teoretycznie nr2 przydać się może raczej do niestandardowych sytuacji. Praktycznie jest dokładnie odwrotnie.
Co do "pure virtual function call", to czy nie można zamiast tego:
class KonkretnaEntity : public Entity
{
public:
  KonkretnaEntity(Kontener *k) : Entity(k) { }
  virtual BOX GetAABB() { return ... }
};
zrobić tak:
class KonkretnaEntity : public Entity
{
public:
  KonkretnaEntity(Kontener *k) : Entity(/*tu nic nie przekazujemy*/) { }
  virtual BOX GetAABB() { return ... }
};
i wywoływać
k->DodajEntity(this);tylko w konstruktorze klasy KonkretnaEntity?
//edit, bo może mało to jasne
Oczywiście każda konkretna klasa encji miałaby dwie wersje konstruktora, jedną przyjmującą kontener*, i drugą domyślną, do wywoływania przez konstruktory pochodnych. To:k->DodajEntity(this); byłoby wywoływane tylko przez najbardziej pochodną, bo tylko dla niej byłby wywoływany konstruktor przyjmujący kontener*. Proponuje zachować jednoznaczny podział na klasy abstrakcyjne i konkretne, wtedy konstruktor Entity(kontener*) nie ma raczej sensu bytu, skoro nie będzie tworzenia obiektów Entity, tylko jej pochodne.
« Ostatnia zmiana: Sierpień 18, 2007, 22:40:17 wysłana przez klosio.neostrada.p »

Offline Xion

  • Redaktor
    • xion.log

# Sierpień 18, 2007, 23:58:40
Tak, to by działało, ale miało zasadniczą wadę: pisząc każdą nową klasę pochodną należałoby pamiętać o tym wywołaniu w jej konstruktorze. Efektem byłoby 0xffffff kopii tego kawałka kodu, który zasadniczo dotyczy obiektów Entity jedynie w ich najogólniejszej postaci. Poza tym oznaczałoby to także konieczność modyfikacji 0xfffff kopii tego kawałka kodu, jeśli cokolwiek się zmieni.

Offline klosio.neostr...

  • Użytkownik
    • Moje Stare Gierki

# Sierpień 19, 2007, 19:12:06
Z drugiej strony jest to jednak na swój sposów eleganckie i naturalne, bo z innymi sposobami jest ten problem, że nigdy nie masz pewności, czy z poziomu pojemnika wywołuje się (przykładowo) funkcja wirtualna TrzeciejPochodnejPoEntity, czy CzwartejPochodnejPoEntity, gdy konstruujesz CzwartąPochodnąPoEntity.
Argument, że przy jednej zmianie trzeba będzie zmieniać ten sam kod w wielu klasach jest bezzasadny, bo można go zamknąć w funkcji, zdefiniowanej w Entity.
Jedyną niedogodnością pozostaje wtedy napisanie wywołania tej funkcji w każdym nowym konstruktorze (nie jest to chyba jakaś katorga). Ale co już zrobisz, zależy od konkretnej sytuacji projektowej, ja tylko pokazuję, jaki jestem mądry ;)

Offline Xion

  • Redaktor
    • xion.log

# Sierpień 19, 2007, 19:35:11
Oj nie bardzo ci wychodzi to pokazywanie mądrości :) Przecież na tym polega cała zaleta funkcji wirtualnych, że nie wiemy, jaka ich wersja jest wywoływana ani nawet jakiego typu jest obiekt, na rzecz którego jest wywoływana. Jeśli to ma powodować jakieś problemy, to jest to po prostu złe użycie tego mechanizmu.

Cytuj
Jedyną niedogodnością pozostaje wtedy napisanie wywołania tej funkcji w każdym nowym konstruktorze (nie jest to chyba jakaś katorga).
Nie jest, ale lepiej jeśli można unikać dodatkowej pracy :)

Offline Reg

  • Administrator
    • Adam Sawicki - Home Page

# Sierpień 19, 2007, 22:44:21
klosio.neostrada.p: Twój pomysł mi się podoba. Gdybym wcześniej nie wymyślił tego co opisałem wyżej, zrobiłbym tak jak napisałeś.