Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
niXon
Založen: 27. 10. 2007 Příspěvky: 22
|
Zaslal: 6. duben 2008, 20:25:23 Předmět: C++: implicitne konstruktory a destruktory... |
|
|
tak zdravim, mam taky maly problem, postupne si skusam priklady z Mistrovstvi v C++ , akurat som na praci s triedami a mam tu taky maly problem... podla toho co som sa docital by malo fungovat nasledovne:
kód: |
#include <iostream>
class string
{
public:
char *data;
int len;
public:
string() {
len = 0;
data = new char[len+1];
data[len] = (char)0; // klasicky nulovy znak na konci
}
string(const char *str) {
len = std::strlen(str);
data = new char[len+1];
std::strcpy(data,str);
}
~string() { delete [] data; }
};
int main() {
string r;
r = "Skuska";
return EXIT_SUCCESS;
} |
no, trosicku som si to debugoval (jednoducho pomocou vypisou a COUT), zistil som kde je asi zadrhel, ale neviem ako ho riesit...
spustaju sa dva konstruktory, prvy krat , pri 'string r' a druhy krat 'r = "Skuska"' to je logicke... v poriadku, ale problem je, ze sa dva krat spusta aj destruktor, co ale uz logicke nieje (teda podla poctu konstruktorov ano, ale nemozeme dva krat mazat ten isty objekt no nie?) ako to mam riesit? pretoze spustenie dvoch destruktorov mi vyvolava crash programu koli snahe dva krat mazat pole data. dakujem |
|
Návrat nahoru |
|
 |
(CZ)genius
Založen: 28. 07. 2007 Příspěvky: 85 Bydliště: Neratovice
|
Zaslal: 6. duben 2008, 20:47:49 Předmět: |
|
|
no já do tohodle zas tolik nevidim, ale rek bych, ze nejdriv se zavola konstruktor pro r. pak se zavola konstruktor pro string("Skuska"), ale ta je jenom docasna.. vytvori se, nastavi dylka atp., priradi se do r a pak se znici (tim se zinvalidni i pointery v r). a pak se nici r, ktere uz mas spatne pointery.. |
|
Návrat nahoru |
|
 |
Quiark

Založen: 29. 07. 2007 Příspěvky: 816 Bydliště: Chlívek 401
|
Zaslal: 6. duben 2008, 21:08:52 Předmět: |
|
|
Jo, jde o to, že při r = "Skuska" se děje toto:
- Vytvoří se třída string z "Skuska"
- Zkopíruje se pomocí operator = (který vytvořil překladač, protože ty ho tam nemáš) ze objektu "Skuska" do objektu r.
- Smaže se objekt "Skuska" a v r zůstane neplatný pointer.
_________________ Mám strach
Naposledy upravil Quiark dne 6. duben 2008, 22:39:02, celkově upraveno 1 krát |
|
Návrat nahoru |
|
 |
rezna
Založen: 27. 07. 2007 Příspěvky: 2156
|
Zaslal: 6. duben 2008, 21:27:15 Předmět: |
|
|
jj jak rika Quiark - chvili mi to sice trvalo - ale je to tak - chybi kopirovaci konstruktor a ten jednoduchy co vytvori kompiler jenom tupe zkopiruje hodnotu pointeru |
|
Návrat nahoru |
|
 |
MePHyst0
Založen: 28. 07. 2007 Příspěvky: 85 Bydliště: SVK/CZK
|
Zaslal: 6. duben 2008, 21:27:37 Předmět: |
|
|
este aby som spravil quiarkovu odpoved kompletnu, musis teda pretazit operator== resp copy constructor
EDIT: beaten by rezna |
|
Návrat nahoru |
|
 |
Quiark

Založen: 29. 07. 2007 Příspěvky: 816 Bydliště: Chlívek 401
|
Zaslal: 6. duben 2008, 21:33:55 Předmět: |
|
|
V tomto případě je potřeba hlavně operator =, pokud se nepletu. Copy constructor se volá jen při vytváření objektu, tedy
kód: |
string r("Skuska");
případně
string r = "Skuska";
|
EDIT: Opraveno z == na =. _________________ Mám strach |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 7. duben 2008, 00:14:06 Předmět: |
|
|
Copy constructor je pěkná svině a volá si i při předávání hodnotou. Nebo když máte nějaký jiný objekt, který předáváte hodnotou, tak i jeho členské proměnné volají kopírovací konstruktor (pokud ho nenapíšete u původní třídy). Je lepší tedy vždy implementovat oba způsoby kopírování. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
niXon
Založen: 27. 10. 2007 Příspěvky: 22
|
Zaslal: 7. duben 2008, 12:18:29 Předmět: |
|
|
dakujem vam vsetkym za rady, tak ako ste povedali, stacilo si spravne nadefinovat operator=() ... tu je funkcny vysledok:
kód: |
#include <iostream>
class string
{
public:
char *data;
int len;
public:
string() {
len = 0;
data = new char[len+1];
data[len] = (char)0; // klasicky nulovy znak na konci
}
string(const char *str) {
len = std::strlen(str);
data = new char[len+1];
std::strcpy(data,str);
}
~string() { delete [] data; }
string &operator=(const string &str) {
delete [] data;
len = str.len;
data = new char[len+1];
std::strcpy(data,str.data);
return *this;
}
string &operator<<(const string &str) {
int nLen = len + str.len;
char *nData = new char[nLen];
char *nData2 = nData;
std::strcpy(nData,data);
nData2 += len;
std::strcpy(nData2,str.data);
delete [] data;
len = nLen;
data = nData;
return *this;
}
};
int main() {
string a,b,c;
a = "Skuska ";
b = "retazca.";
c << a << b << " A druha skuska.";
std::cout << c.data << "\n";
return EXIT_SUCCESS;
} |
|
|
Návrat nahoru |
|
 |
rezna
Založen: 27. 07. 2007 Příspěvky: 2156
|
Zaslal: 7. duben 2008, 12:28:15 Předmět: |
|
|
mno kdyz uz jsme u toho
kód: |
public:
char* data;
int len; |
tak takhle fakt ne - o zapouzdreni tu probehla uz spousta diskuzi a je to dobre si ho uvedomit a zacit pouzivat drive nez ziskas spatne navyky |
|
Návrat nahoru |
|
 |
Augi

Založen: 28. 07. 2007 Příspěvky: 782 Bydliště: Čerčany
|
Zaslal: 7. duben 2008, 13:46:35 Předmět: |
|
|
Imho evidentně překlep, protože tam má 2x nad sebou "public:"  |
|
Návrat nahoru |
|
 |
niXon
Založen: 27. 10. 2007 Příspěvky: 22
|
Zaslal: 7. duben 2008, 13:58:10 Předmět: |
|
|
eh, jasne sorry, samozrejme ze ma byt private, ale nechcelo sa mi pisat dalsiu funkciu getData (potrebujem to v main funkcii), ale pre spravnost mate pravdu... islo o iny problem v kode... |
|
Návrat nahoru |
|
 |
Al
Založen: 23. 10. 2007 Příspěvky: 196
|
Zaslal: 7. duben 2008, 23:59:46 Předmět: |
|
|
Divím se, že tak základní věci v té vaší knize nejsou. Základní myslím jako smrtelně důležité, ne jako jednoduché. Jistě uznáte, že toto je doslova smrtelné. Každá třída v C++ musí prostě mít mimo jasné věci i korektní "copy konstruktor" a "přiřazovací operátor".
P.S. Doporučuji knihu M.Virius: Pasti a propasti C++ |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 8. duben 2008, 00:06:40 Předmět: |
|
|
Ne, každá třída nemusí. Pouze třídy vlastnící pointer do paměti musí ty kopírovací funkce mít a to jen tehdy, když je třeba při jejich kopii také kopírovat obsah paměti, kam pointery ukazují. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
Al
Založen: 23. 10. 2007 Příspěvky: 196
|
Zaslal: 8. duben 2008, 00:10:19 Předmět: |
|
|
Podle mě musí každá třída, jak jsem napsal. Jen u těch triviálních, co uvádí Eosie, můžeme použít to, co tam automaticky vygeneruje překladač, a nemusíme to definovat sami. |
|
Návrat nahoru |
|
 |
|