konstruktor és destruktor osztaly::tagfuggveny formában az osztály leírásában

 ( lzrd | 2008. február 27., szerda - 18:04 )

Sziasztok!

Ezen az oldalon:
http://209.85.129.104/search?q=cache:BwKToFMwucYJ:www.keil.com/support/docs/3136.htm+undefined+reference+to+constructor+destructor&hl=hu&ct=clnk&cd=1&gl=hu

találtam az alábbi részletet:

class clf  {
  public:
   clf();               // Constructor (ctor)
  ~clf();               // Destructor (dtor)
   int   n1, n2, n3;
};

clf::clf ()  {          // define ctor
  n1 = n2 = n3 = 0;
}

clf::~clf()  {          // define dtor
}

clf clf1;               // class object

int main (void)  {
  return (0);
}

Miért kell az osztály leírása után külön definiálni a konstruktort és a destruktort?
Az osztálydefiníción belül nem lehet? És akkor nem kéne a láthatósági(?) operátort (::) használni. Ha itt a dupla kettőspont nem láthatósági operátor, akkor elnézést!

Szóval az alábbi példa miért rossz?

class clf  {
  public:
   clf()                // Constructor (ctor)
        {
         n1 = n2 = n3 = 0;
        }               
  ~clf();               // Destructor (dtor)
   int   n1, n2, n3;
};

clf clf1;               // class object

int main (void)  {
  return (0);
}

Köszi a választ!

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Mind a ket verzio jo, de amikor kivul definialod a tagfuggvenyeket, akkor lehetoseged van arra, hogy a deklaracio es a definicio kulon allomanyban legyen. Ez meg azt teszi lehetove, hogy a leforditott koddal csak a deklaraciokat kell csak adni az osztaly felhasznaloinak. Igy a clf osztaly implementaciojanak hipertitkos reszleteit csak disassemblerrel lehet kideriteni. :)

Van meg egy elonye a kulon file-ban torteno definicionak: ha valtozik az implementacio, de az osztaly interfesze nem, akkor egyszeru ujralinkelessel (dinamikus linkeles eseten meg az sem kell) maris lehet hasznalni, nem kell ujraforditani a cuccot. Ez mondjuk nem mukodik ilyen szepen, de anno azt szerettek volna az okosok ha igy mukodne. Ettol is elcseszett egy kicsit a c++.

Köszönöm a választ!
Kinyomtatom, hazaviszem és megpróbálom megérteni.

--
unix -- több, mint kód. filozófia.
Life is feudal

Template-eknel kenyelmesebb 2. felekeppen, es nincs is sok ertelme masutt implementalni.

A peldad azert rosz, mert csak egy fejet adtal meg detruktornak. ~clf(){}; vagy nem is kell oda.

Azert nem jo igy deklaralni, mert egy masik forditasi egysegbol(c++ file) akkor, hogy ered el az ossztalyt ?
Erdemes header-be kitolni a deklaraciot es valamelyik c++ forras fileban implemantalni.

"Azert nem jo igy deklaralni, mert egy masik forditasi egysegbol(c++ file) akkor, hogy ered el az ossztalyt ?"

Jó az így. Mit értesz amúgy ez alatt?

Pl. egy ilyen felallas:

Header-file  
 osztaly deklaracio(k)
c++-file
 include header-file
 Osztaly implementacio(k)
c++-file
 include header-file
 Osztaly hasznalata - peldanyositas..
 (Opcinalisan tovabbi osztalyok deklaralasa, hasznalata,..)

Én ezt a megoldást választottam és műxik és tetszik.
(Feltételezem Header-file1 == header-file)
--
unix -- több, mint kód. filozófia.
Life is feudal

A fordító ismeri a méretét, hiszen deklarálva van a header fájlban. Így bárhonnan elérhető. A definíció pedig szabadon módosítható (osztálymetódusok törzse).

class -on belul implementalod g++ ki sem exportalja alabol.

Ha meg is raveszed, es veletlenul elteres van mondjuk az adattagok sorrendjeben, akkor friend -jeit alaposan megzavarod, es kurva sokaig keresheted hol a hiba..

A peldad jo, de a destruktor nincs definialva. Egy kis kiegeszites:

class clf  {
  public:
   clf();               // Constructor (ctor)
  ~clf();               // Destructor (dtor)
   int   n1, n2, n3;
};

clf::clf(){};
clf::~clf(){};

A kettospontok azert kellenek, mert mar kivul vagy az osztalyon, meg kell mondani, hogy mit is definialsz.

Ha rogton definialni is szeretned a konstruktort/destruktort:
class clf{
   clf(){};               // Constructor (ctor)
  ~clf(){};               // Destructor (dtor)
[...]
};

Tehat ket fele keppen is lehet. Definicio lehet a deklaracioval egyutt, vagy kulon (masik fileban, libraryban, mindegy). Lenyeg, hogy csak egy legyen :)

Member valtozoknak pedig erteket igy is lehet adni:

  clf():n1(0),n2(0),n3(0){};

Az osztaly helyesen:

class clf  {
public:
  clf():n1(0),n2(0),n3(0){};               // Constructor (ctor)
  ~clf(){};                                // Destructor (dtor)

  int   n1, n2, n3;
};

Andras

en ugy tudom, hogyha osztalydefinicion belul definialod a tagfv-t (legyen ez akar konstruktor, akar destruktor), akkor az azt teszi, mintha te a kodban osztalydefinicion kivul definialnad a fv-t inline kulcsoszoval
bovebben az inline fuggvenyekrol itt: http://en.wikipedia.org/wiki/Inline_function

Otthon utánaolvastam és én is azt találtam, hogy ha egyszerre van deklarálva és definiálva, vagyis a definiálod az osztályt, akkor a tagfüggvények inline függvények lesznek. És megtaláltam azt is, hogy a saját gyakorló kódomban mi volt a baj. Ha függvényt raktam fejállományba ÉS cpp állományba, akkor a fejállományban deklaráltam, a cpp fájlban, amiből object-et lehet fordítani, pedig definiáltam a függvényt. Viszont az nem esett le, hogy osztály esetén a deklarációban megadom az osztály szerkezetét, de a deklarációban már magát a szerkezetet nem írom le mégegyszer, csak a tagfüggvényeket fejtem ki és ezért van szükség a láthatósági(?) hatókör(?) operátorokra a tagfüggvény neve előtt. Ezt nem értettem még tegnap.
--
unix -- több, mint kód. filozófia.
Life is feudal

Szerintem ez igy hulyeseg. Attol meg, hogy az osztalydeklaracioban definialsz egy fuggvenyt, attol meg veheted a cimet (ami szerintem kizarja az inline-t), sot lehet virtualis is, ami szinten fura lenne inline-kent (merugye vtbl-be a fuggveny cime kerul)....

Nyilván nem fogok veled ezen vitázni. Lehet, hogy igazad van, lehet, hogy nem. Majd mások megmondják.
--
unix -- több, mint kód. filozófia.
Life is feudal

Nem hülyeség, inline lesz. Ettől még veheted pl. a címét, mert legfeljebb lesz egy "normál" függvény is a tárgykódban, amit indirekt címzéssel tud hívni, ahol meg teheti, kifejti a függvényt a kódban. Gondolom, ez már compiler-függő amúgy.

Szerk.:
Ráadásul az inline csak egy kérés, amit a compiler vagy teljesít vagy nem.

Inline functions, though declared that way, are not always inlined. It is not always necessary to declare a function as inline. Any function whose body is defined within the class body will be implicitly treated as inline. But there is a catch to this. The implicit treatment depends on the complexity and length of the function. Remember who is the boss when it comes to inline functions? Inline is just a request and it is the compiler who is vested with the authority to accept or reject the inline request.

KisKresz

Ja, csak pl. explicit inline fuggvenynek a cimet nem lehet venni, ergo valami kulonbseg van.... Szerintem van kulonbseg az explicit inline fuggveny es a fordito altal inline optimalizacios celpontkent meghatarozott fuggveny kozott.

Nem lehet a címét venni?

#include <iostream>

inline int f( int a ) { 
    return a + 1;
}

int main( int /* argc */, char* /* argv */ [ ] ) 
{
    int ( *pf )( int ) = f;

    std::cout << f( 2 ) << std::endl;
    std::cout << pf( 3 ) << std::endl;                                                                                                      

    return 0;
}

KisKresz