» »

operator +

operator +

MasterBlaster ::

Imam en custom string class CMyStr in na njem deklariran operator +:

friend CMyStr operator+(const CMyStr& first, const char* other);

Ideja je v tem, da bi naj dva stringa zlepil skupaj. Zadeva špila na MSVC in gcc 3.x, sedaj pa poskušam zadevo prevesti na gcc 4.

Koda:

CMyStr str;
str = "abc";
str = str + "efg";

Javi napako :

./AdmUporabniki.cpp:728: error: no matching function for call to CMyStr::CMyStr(CMyStr)
../MyLib/MyStr.h:176: note: candidates are: CMyStr::CMyStr(const char*)
../MyLib/MyStr.h:175: note: CMyStr::CMyStr(unsigned int)
../MyLib/MyStr.h:71: note: CMyStr::CMyStr(CMyStr&)


Če kličem samo kot:

str + "efg";

ali

str = (str + "efg").c_str() // .c_str() vrne const char *;

pa deluje. Kaj storiti?
Tk je pa pika .

Vesoljc ::

fajn bi bilo videti se konstruktorje tega stringa...
Abnormal behavior of abnormal brain makes me normal...

MasterBlaster ::

CMyStr();
CMyStr(unsigned int chunksize);
CMyStr(const char * string);

Na sploh mi ni jasno zakaj se sploh kliče konstruktor. V funkciji CMyStr operator +(CMyStr &first, const char* other), se alocira ena spremenljivka tipa CMyStr, ki se potem kot rezultat vrne na stack.

Sedaj sem malo popravil, tako, da imam eno globalno spremenljivko, ki jo v funkciji napolnem, potem pa trnem referenco;


CMyStr CMYSTR_RETURN_VAL;
CMyStr &operator+(const CMyStr& first, const char* other){
CMYSTR_RETURN_VAL.Clear();
CMYSTR_RETURN_VAL += first;
CMYSTR_RETURN_VAL += other;
return CMYSTR_RETURN_VAL;
}

S tem sem sicer izgubil thread safty samo vsaj str = str + "abc" dela. Bol kompleksni primer kot:

str = str + "[" + str2 + "]";

Pa še vedno javi enako napako.
Tk je pa pika .

64202 ::

Kako pa zgleda tvoj operator =?
I am NaN, I am a free man!

64202 ::

> str = str + "efg";

Bi rekel da se iz navedenega lahko zgodi tole:
operator + (...) {
   CMyStr Ret;
    str + "efg" nastima Ret
    return Ret;
}

return Ret se potem prevede v:
CMyStr Tmp(ret);

in potem se na koncu:

str = Tmp;


Lahko se pa zgodi tudi tole (g++ 3.2/3.3/3.4 precej zagreto optimizirajo konstruktorje):
operator + (...) {
   CMyStr Ret;
   str + "efg" nastima Ret
   return Ret;
}

return Ret se pa potem prevede kar v:
str = Ret;


Torej, odvisno je kako compiler optimizira in to lahko odkrije kako dodatno napako v tvoji kodi.
I am NaN, I am a free man!

MasterBlaster ::

Hvala za pomoč, sam mi je sedaj uspelo usposobiti zadevo. Drfiniral sem svoj copy constructor CMyStr(const CMyStr &)) in sedaj zadeva dela.
Tk je pa pika .

Gundolf ::

MAsterBlaster, če še spremljaš temo, ti dam še en nasvet. Kontruktor
CMyStr(unsigned int chunksize);
spremeni v
explicit CMyStr(unsigned int chunksize);
da se ti ne bo še kaj čudnega dogajalo (recimo avtomatska pretvorba iz unsigned int v CMyStr).

Sem te hotel napotiti na nadalnje branje a pravzaprav imam čas da ti vsaj malo razložim tole. Konstruktorji se včasih uporabljajo tudi za pretvorbo tipov. Recimo v tvojem primeru lahko poskusiš tole (še preden dodaš tisti explicit):
dodaš funkcijo (lahko tudi kaj naredi ta funkcija, če želiš preveriti ali se res izvede)
funkcija (CMyStr str) {}
in potem kličeš funkcijo takole:
funkcija("ahaha!");
funkcija(10);
Prevajalnik bo oboje požrl, ker bo za oba primera našel konstruktorja z enim parametrom (unsigned int oz. const char*.) s pomočjo katerega lahko ta parameter pretvori v CMyStr in ga nato podtakne funkciji. V prvem primeru je to celo zaželjeno v drugem pa verjetno ne. Zato uporabiš explicit, kar pomeni, da se konstruktor ne sme uporabljati za pretvorbo ampak se sme uporabiti explicitno le za konstrukcijo, se pravi, ko ga sam direktno kličeš.

Pa še ena malenkost:
CMyStr &operator+(const CMyStr& first, const char* other);
to je nadvse slabo.
CMyStr operator+(const CMyStr& first, const char* other);
tako se pa to dela. Če seštevaš dve vrednosti se razume da boš dobil neko novo vrednost. Optimizacija s referencami tu ne pride v poštev (niti ni ne vem kako uspešna optimizacija tole). Poleg tega ima pa še eno hudo napako:
CMyStr a("a"), b("b"), c("c"), d("d");
a = b + c + d;
Ugani vrednost a :D

Če že nujno hočeš sam spisati String class potem si vsaj poglej katere funkcije in konstruktorji so implementirani pri std::string, ker sam boš zelo težko kaj boljšega iznašel.

MasterBlaster ::

CMyStr(unsigned int chunksize);
spremeni v
explicit CMyStr(unsigned int chunksize);


Hvala za opozorilo, bom spremenil.

Pa še ena malenkost:
CMyStr &operator+(const CMyStr& first, const char* other);
to je nadvse slabo.
CMyStr operator+(const CMyStr& first, const char* other);


Ja vem, saj tako sem imel originalno narejeno. Tisto z referenco je bil le en poskus workaround-a omenjenega problema.
Tk je pa pika .


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[C] struct in int[] (strani: 1 2 )

Oddelek: Programiranje
657321 (6394) MrBrdo
»

[C++] Kopiranje char arraya v drug char array

Oddelek: Programiranje
71271 (1142) win64
»

Pomoc v C-ju

Oddelek: Programiranje
51288 (1200) rfmw
»

[C++] Pretvorba iz int v char *

Oddelek: Programiranje
232962 (2338) Gundolf
»

c++ datoteke

Oddelek: Programiranje
464038 (3527) Vesoljc

Več podobnih tem