-
21. Data: 2012-07-05 13:38:29
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: Andrzej Jarzabek <a...@g...com>
On Jul 5, 9:20 am, "slawek" <h...@s...pl> wrote:
> Użytkownik "Paweł Kierski" napisał w wiadomości grup
> dyskusyjnych:jt3ab8$g...@i...gazeta.pl...
>
> >Pytanie, dlaczego nie Foo::run(), czyli metoda statyczna, czyli zwykła
> >funkcja? Domyślam się, że z powodu dużego skomplikowania funkcji,
>
> To nie tego rodzaju problem. Jeszcze raz, bo mogło nie być oczywiste -
> pytanie jest bowiem nie o to "jak załatać konkretną dziurę" - i przez to
> nieco teoretyczne.
> Poniżej masz przykłady używania metody run() lub podobnej. Pytanie było: czy
> naprawdę musi być run() - czy nie wystarczyłoby, aby konstruktor robił całą
> robotę?
>
> W Borlandowskim OWL jest (vide np.http://www.tenermerx.com/owlhow/items/tutorial/st
ep1.html)
>
> TApplication app; // odpalany jest konstruktor
> return app.run(); // odpalana metoda run
>
> W Qt jest (vide np.http://pl.wikibooks.org/wiki/Programowanie_C%2B%2
B_Qt4_w_systemie_Gnu...)
>
> QApplication app(argc,argv);
> return app.exec();
>
> Natomiast w MFC niesposób znaleźć "execute" czy "run" - dzieje się samo, bez
> popychania. Być może run() siedzi gdzieś przyczajone globalnie.
MFC po prostu dolinkowuje ci entry point do execa który wywołuje Run()
na zarejestrowanym obiekcie CWinApp.
W przypadku statycznych (w tym globalnych) obiektów umieszczanie
działania w konstruktorze jest o tyle ryzykowne, że dla nietrywialnie
konstruowanych typów kolejność inicjalizacji pomiędzy jednostkami
translacji nie jest wyspecyfikowana.
Pewną dość oczywistą wadą 'uruchomienia przez konstruktor' jest brak
możliwości sensownego dziedziczenia po takiej klasie. W C++ dodatkowo
w takich przypadkach występuje problem z wywoływaniem funkcji
wirtualnych z konstruktora.
-
22. Data: 2012-07-05 15:36:06
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: Paweł Kierski <n...@p...net>
W dniu 2012-07-05 13:38, AK pisze:
[...]
> Osobiscie staram sie trzymac sie zasady, ze w konstrulktorzae(ach) winno
> byc jedynie
> _to co niezbedne_ to utworzenia obiektu, a ew akcje sa jako osobne metody
> (ew wolane w konstruktorze, ale mozliwie minimalizujac do
> oczywistych/narzucajacych sie
> przypadkow taki wolania).
W sumie najlepszy argument na "nie" - łatwo dopisać:
void foo()
{
Foo().run();
}
trudniej "rozkleić" istniejący konstruktor.
--
Paweł Kierski
n...@p...net
-
23. Data: 2012-07-05 15:49:23
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: "slawek" <h...@s...pl>
Użytkownik "Maciej Sobczak" napisał w wiadomości grup
dyskusyjnych:15ad6c49-e409-40a2-a76f-c15cd00ab57b@go
oglegroups.com...
>Jeśli konstruktor i run() zawsze idą w parze i nie są rozdzielone innymi
>operacjami (spekulacja: można mieć listę takich obiektów? można je zapisać
>i odczytać? itd.), to można. Ale dlaczego się >na tym zatrzymywać? Jeżeli
>zaraz po run() obiekt i tak jest niszczony, to całość można zebrać w jedną
>funkcję runFoo().
Nie, nie można zebrać w jedną funkcję, bo obiektów tej klasy może być wiele
a każdy ze swoimi własnymi polami private, protected i public.
>Paweł podał argument, że być może ta funkcja jest skomplikowana i korzysta
>z usług innych klas, które odwołują się do pól Foo - ale to niewiele
>zmienia, bo skoro tym innym klasom trzeba >podać referencje do tych
>wykorzystywanych pól, to równie dobrze można im podać referencje do
>odpowiednich zmiennych lokalnych stworzonych w run().
Moim zdaniem bardzo kiepski pomysł - taki na poziomie C bez plusów.
>Podejrzewam tu po prostu nadmiar nieuzasadnionej "obiektowości".
Wszystko można zrobić w Fortranie. A być może Cobolu.
>> 2. Czy metodę run() można wywoływać w konstruktorze
>Można.
I to - patrząc na dyskusję na innym, anglojęzycznym, forum - jest nieco
wątpliwe. De facto konstruktor dla obiektów danej klasy może wywoływać się
niejako "przypadkowo" - np. gdy utworzy się zmienna tymczasowa. Ponadto -
AFAIR - dopiero po opuszczeniu konstruktora obiekt jest skonstruowany. Więc
run() wywołana wewnątrz po prostu działałaby na nieskonstruowanym
obiekcie... Ale z drugiej strony to nigdzie nie ma formalnie opisanego
"czego nie wolno w konstruktorze". IMHO w konstruktorze obiekt już w 100%
istnieje... pozostaje tylko dodać to co chcemy (i co być może MY uznajemy za
dodanie wisienki by obiekt był kompletny). Więc jeżeli uporamy się z
wisienką, to możemy konstruktor dowolnie mocno eksploatować.
>W takim razie nie ma potrzeby ich rozdzielać.
To po co rozdzielają to niemal w każdej z bibliotek GUI? Przez głupotę, czy
przez niewiedzę?
-
24. Data: 2012-07-05 16:08:54
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: "slawek" <h...@s...pl>
Użytkownik "Roman W" napisał w wiadomości grup
dyskusyjnych:bd373b26-93c8-4d46-b671-a240746af7af@go
oglegroups.com...
>1. przygotuj zmienne lokalne (np. rozpakuj dane wejsciowe, ustaw
>odpowiednie opcje)
>2. wykonaj potrzebna operacje
>3. posprzataj po sobie
To da się zrobić np. tak
class Foo
{
public:
Foo()
{
prepare_local_variables();
execute_necessary_operations();
}
private:
prepare_local_variables() ... // etc.
};
Oczywiście, nieco przydługawo, jednak ważne jest, iż na zewnątrz widać tylko
Foo() oraz domyślny destruktor (ew. niedomyślny). Oczywiście
prepare_local_variables() może być "wewnętrznym standardem de facto", można
rozbić to na drobniejsze fragmenty, można execute_necessary_operations()
robić jako:
void Foo::execute_necessary_operations()
{
execute_internal_operations();
execute_external_operations();
while( execute_additional_operations() != NO_MORE_BEER_OR_OPS)
execute_run(get_param(those->this->where->there));
}
Zachowana jest jednak zasadnicza "filozofia" RAII - utworzenie obiektu
uruchamia proces (rozumiany jako "zasób") - skasowanie obiektu proces
zatrzymuje. Niepotrzebny jest dodatkowy run(), który byłby widoczny na
zewnątrz i w dodatku wymagał wzmianki dla użytkownika (użytkownika klasy) w
dokumentacji.
Innymi słowy - wsiadasz do samochodu na miejsce kierowcy i samochód ciebie
rozpoznaje sam, sprawdza czy jesteś właścicielem, czy masz prawo jazdy, czy
jesteś trzeźwy itd. Nawet nie musisz wiedzieć co to jest np. alkoholomat czy
kluczyki.
-
25. Data: 2012-07-05 16:18:47
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: "slawek" <h...@s...pl>
Użytkownik "AK" napisał w wiadomości grup
dyskusyjnych:jt3ub8$f4h$...@i...gazeta.pl...
>Gdyz (rowniez z reguly) "wpakowujac" kod run() w konstruktor tracisz wtedy
>polimorfizm run().
Niekoniecznie. Kod "run" z konstruktora może np. sięgać do metod
wirtualnych. Nawet nie o to chodzi, by nie było run() w ogóle - ale aby nie
było publicznego run() które musiałby wywoływać użytkownik klasy/obiektów.
>Duzo zalezy od jezyka, ale niektore z nich nie lubia wyjatkow (a wiec
>"wlasnosc" akcji/metod)
>rzucanych z konstruktora.
Gimnastyczną metodą jest w MS Windows odpalenie PostMessage w konstruktorze,
np. z WM_USER+1. Konstruktor wyzwala run(), ale samo run() jest niewidoczne
z zewnątrz. I nie jest w konstruktorze.
-
26. Data: 2012-07-05 16:24:53
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: "slawek" <h...@s...pl>
Użytkownik "Andrzej Jarzabek" napisał w wiadomości grup
dyskusyjnych:7a3451d2-b497-461a-8a6e-b79d7ffdad57@a1
6g2000vby.googlegroups.com...
>Pewną dość oczywistą wadą 'uruchomienia przez konstruktor' jest brak
>możliwości sensownego dziedziczenia po takiej klasie. W C++ dodatkowo
>w takich przypadkach występuje problem z wywoływaniem funkcji
>wirtualnych z konstruktora.
Ale przecież konstruktor tej klasy może być sparametryzowany i jednocześnie
domyślny konstruktor może być pusty. No problem.
Chyba vtable jest już wypełniona przed wejściem w blok {} konstruktora? Bo i
niby czemu nie miałaby być?!
-
27. Data: 2012-07-05 16:27:46
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: "slawek" <h...@s...pl>
Użytkownik "Paweł Kierski" napisał w wiadomości grup
dyskusyjnych:jt4588$o34$...@i...gazeta.pl...
>W sumie najlepszy argument na "nie" - łatwo dopisać:
>void foo()
>{
> Foo().run();
>}
>trudniej "rozkleić" istniejący konstruktor.
Można też
#define foo (Foo().run())
Jednak argument o "rozklejaniu" jest chybiony - celem sklejenia mogłoby
przecież być uniemożliwienie rozklejenia (i np. dwa razy wywoływania run()
dla jednego obiektu).
-
28. Data: 2012-07-05 16:52:00
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: "AK" <n...@n...com>
Użytkownik "Paweł Kierski" <n...@p...net> napisał:
> łatwo dopisać:, trudniej "rozkleić" istniejący konstruktor.
Dzieki.
Dokladnie o to mi chodzilo, ale Ty (jak zwykle) lepiej/jasniej to wyraziles.
AK
-
29. Data: 2012-07-05 18:59:50
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: Michoo <m...@v...pl>
On 05.07.2012 09:38, slawek wrote:
> Użytkownik "Artur M. Piwko" napisał w wiadomości grup
> dyskusyjnych:slrnjvadpo.8la.milusi.pysiaczek@buziacz
ek.pl...
>
>> Pytanie dlaczego nie jeśli po wykonaniu nie będzie potrzebny:
>> int Foo_run() {...}
>
> Odpowiedź oczywista: bo w trakcie działania ma tworzyć inne obiekty,
> mające referencje do pól, a w szczególności do jego this.
To nie jest problem, bo obiekt jest na etapie konstruktora już zainicjowany.
--
Pozdrawiam
Michoo
-
30. Data: 2012-07-05 19:06:44
Temat: Re: Co może robić konstruktor i dlaczego nie?
Od: Michoo <m...@v...pl>
On 05.07.2012 08:29, slawek wrote:
> Użytkownik "Michoo" napisał w wiadomości grup
> dyskusyjnych:jt2mjk$hud$...@m...internetia.pl...
>
>> Foo().run();
>
> Ok, też można. Nie zrozumiałeś jednak pytania. Bo to co proponujesz to
> dalej używanie metody run/execute/command/...
Tak jest jeszcze prostszy zapis a czas życia ograniczony do niezbędnego
minimum.
>
> A chodziło o taką "filozofię", w której samo istnienie obiektu uruchamia
> jego działanie.
Taka filozofia z run w konstruktorze ma wiele niefajnych implikacji - np
ciężko się dziedziczy, ciężko się debuguje, ciężko się potem zmienia, etc.
No i jest nieintuicyjna dla kogoś kto potem to będzie rozwijał - jeżeli
mamy "obiekt" to zakłądamy trzy fazy życia:
- utworzenie
- praca na obiekcie
- zniszczenie
>
> Czyli nie ma potrzeby "mieć obiekt i potem kazać mu coś zrobić" - tylko
> "obiekt robi coś, bo po prostu istnieje".
>
To czemu nie funkcja? Musisz tworzyć obiekt?
--
Pozdrawiam
Michoo