Warsztat » Forum

[Programowanie] Jawne wywołanie konstruktora/destruktora

Oct 31, 2005 | l1nk |
24 wypowiedzi na 2 stronach:
1 2
l1nk
Oct 31, 2005

Jawne wywołanie konstruktora/destruktora

Witam, mam pytanie natury technicznej :)
Chcialem zrozumiec mniej wiecej zasade jawnego wywolywania powyzszych funkcji i w tym celu splodzilem nastepujacy krotki kod

Kod: 


#include <iostream>
#include <conio.h>

using namespace std;

class test
{
public:
   test();
   ~test();
};

test::test()
{
   cout << "Pracuje konstruktor " << endl;
   getch();
}

test::~test()
{

   cout << "Pracuje destruktor" << endl;
   getch();
}

///////////////////////////////////////////////////

int main()
{

   cout << "Poczatek programu" << endl;

   test asd;

   cout << "Po utworzeniu obiektu jawne wywolanie destruktora" << endl;

   // asd.test(); 


   asd.~test();
   asd.test::test();
   asd.test::~test();

   cout << "KONIEC" << endl;

   return 0;
}



I teraz mam kilka pytani:

1) dlaczego mozliwe jest jawne wywolanie konstruktora dla obiektu asd w formie asd.test::test();  jesli nie jest ono mozliwe dla asd.test(); ?
2) czy konstruktor mozna w ogole wywolywac dla obiektu juz stworzonego?
3) czy konstruktor zajmuje sie tworzeniem danego obiektu czy moze jedynie inicjalizuje stworzony juz obiekt konkretna wartoscia?

Z gory dziekuje :) Mam nadzieje tylko, ze jak popelniam gdzies blad w rozumowaniu to nie bedzie to powod do mieszania mnie z blotem :P Kazdy chyba kiedys zaczynal :)

Pozdrawiam :)



Estelhof
Nov 2, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Kod: asd.test();

To nie działa, bo konstruktor wywołujemy do tworzenia obiektu, czyli nie używaj go na rzecz asd, bo ten zostaje wcześniej stworzony (konstruktorem domniemanym). Wywoływanie konstruktora na rzecz stworzonego już obiektu, abstrahując od tego czy to dopuszczalne, jak dla mnie to bez sensu ;)
Natomiast co do:
Kod: asd.test::test();
asd.test::~test();

Skoro zaczynasz to daj sobie spokój z takimi konstrukcjami ;D
benethorpl
Nov 2, 2005

Odp: Jawne wywołanie konstruktora/destruktora

@3. Konstruktor inicjalizuje pola obiektu ;)
l1nk
Nov 5, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Estelhof, ja nie szukam odpowiedzi czy wywolywanie konstruktora dla utworzonego obiektu ma jakis sens czy nie, chce sie dowiedziec czemu jezeli jawne wywolanie konstruktora w stylu asd.test::test(); jest mozliwe to czemu nie da sie go wywolac w sposob asd.test();

A co do tworzenia obiektu to konstruktor sie tym nie zajmuje tak jak to benethorpl napisal, wiec wywolywanie go dla obiektu juz istniejacego jest poprawne. W koncu przeciez w linii z asd.test::test(); jak chyba zauwazyles (albo nie ;p) wywoluje wlasnie ten sam konstruktor.

Blad asd.test(); jest bledem skladniowym, visual mi wyrzucil komunikat przy tej linii ze:

1>c:\documents and settings\l1nk\pulpit\rav\projekty\c\visual studio\eggs\eggs\main.cpp(38) : error C2274: 'function-style cast' : illegal as right side of '.' operator

a linie asd.test::test(); skompilowal bez problemu, bez problemu rowniez program je wykonuje bo nastepuje wywolanie tych konstruktorow i destruktorow tak jak powinno ono wygladac. Tyko meczy mnie czemu asd.test(); jest przez kompilator odrzucane.


edit: I gdzie ja powiedzialem ze dopiero zaczynam? :D
albireo
Nov 3, 2005

Odp: Jawne wywołanie konstruktora/destruktora

gcc (dokładniej to wersja 3.4.2 z mingw) nie kompiluje też tego: asd.test::test(); komunikat dokładnie taki sam jak dla asd.test(); czyli "error: invalid use of `class test'"
l1nk
Nov 3, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Dev podobnie ma z tym problemy, ale Visual 2008 Express Edition łyka bez mydła ;u
albireo
Nov 4, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Cytat:

Dev podobnie ma z tym problemy, ale Visual 2008 Express Edition łyka bez mydła ;u

Pewnie dlatego, że dev używa gcc z mingw jako kompilatora, sprawdziłem jeszcze na wersji 4.4.0 i to samo, wygląda na to, że takie wywołanie jest niezgodne ze standardem c++ (to że visual to łyka, to może być tylko jakieś jego rozszerzenie), poprawne 'ręczne' wywołanie konstruktora ma postać new(&asd) test(); lub new(&asd) test::test(); .
Mormegil
Nov 4, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Konstruktor ma "tworzyc" instancje. To ze w praktyce ja tylko inicjalizuje nie ma tu znaczenia. Ma byc uzywany w taki oto sposob:
Kod: test a(parametry);
test * b = new test(parametry);


@2 Dwukrotne "tworzenie" tego samego obiektu, to proszenie sie klopoty. Konstruktor moze alokowac pamiec, tworzyc dynamiczne obiekty itd. Kto to zwolni ? Juz wystarczajaco duzo klopotow jest z new i delete.
@1 Skoro gcc nie pozwala na takie zachowanie, to mozna spokojnie przyjac, ze VS poprostu nie trzyma standardu. A jesli chcesz miec pewnosc to zajrzyj do standardu, pewnie jest napisane czy takie konstrukcje sa przewidziane, czy nie.

Jezeli bardzo potrzebujesz powtornie inizjalizowac obiekty, np. po to by przywrocic im stan poczatkowy, to najlepiej zrobic sobie metode "Init", ktora tak naprawde odwali cala robote konstruktora.
l1nk
Nov 6, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Wiec zakladajac ze mam jakas funkcje skladowa to wywolanie w stylu obiekt.klasa::funkcja(); jest tym samym co obiekt.funkcja(); pod warunkiem ze funkcja nie jest wirtualna? :) Obydwa wywolania sa rownowazne?
Kos
Nov 6, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Wedle mojej wiedzy, tak. Zauważ, że funkcja sobie po prostu istnieje gdzieś w pamięci w jednym egzemplarzu i w sumie nie ma nic wspólnego z obiektem - poza tym że nazywa się klasa::funkcja . Prefiks "obiekt." jest po to, by w elegancki sposób przekazać do niej parametr "this".
A w dodatku masz taką wygodną możliwość, że wywołując metodę nie musisz specjalnie pisać tego prefiksu "klasa::", bo kompilator sobie go sam potrafi rozgryźć na podstawie typu obiektu (early linking). Dla funkcji wirtualnych kompilator przy takim "bezklasowym" wywołaniu nic nie rozgryza, bo program dopiero w momencie odpalenia funkcji sam znajduje ją sobie w vtable - late linking).

[size=8pt]nic nie przekręciłem? :-)[/size]
bies
Nov 7, 2005

Odp: Jawne wywołanie konstruktora/destruktora

1) Żadne z wywołań nie jest poprawne.
2) Można (przez placement new -- przykład podał albireo). Warto wcześniej wywołać destruktor na obiekcie który zamazujesz.
3) Konstruktor tworzy obiekt (część obiektu) w przekazanej mu pamięci. W praktyce nie różni się to wiele od inicjacji składowych.
4) O to nie pytałeś (;D) ale pamiętaj, że konstruktor to nie jest metoda.
l1nk
Nov 7, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Tylko ze w podobny sposob przy uzyciu specyfikatorow zakresu mozna wywolywac funkcje skladowe jednej klasy dla obiektu klasy drugiej :)
Z ciekawosci zrobilem takie wywolanie i kompilator je odrzucil z powodu niemoznosci dokonania konwersji typu A na typ B. Jest to wg mnie zrozumiale ;d ale zastanawiam sie teraz w jakich sytuacjach mozna takich wywolan dokonywac (pod warunkiem ze A nie jest klasa pochodna klasy B)
bies
Nov 7, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Jeżeli A nie jest pochodną B takie wywołanie jest błędne.
l1nk
Nov 7, 2005

Odp: Jawne wywołanie konstruktora/destruktora

a jezeli zdefiniowany zostala funkcja kowertujaca typ A na B? :P Wydaje mi sie, ze wtedy wywolanie bedzie ok mimo braku dziedziczenia :)
bies
Nov 7, 2005

Odp: Jawne wywołanie konstruktora/destruktora

Ależ sprawdź sobie. Dobrym testem zgodności ze standardem C++ jest Comeau C++ (test dostępny online).
l1nk
Nov 7, 2005

Odp: Jawne wywołanie konstruktora/destruktora

dziekuje bardzo :) temat wyczerpany :P
Strony:
1 2