Hej. Mam problem z przeciążonymi operatorami '=' i '+'. Deklaruję klasę cTekst służącą do manipulacji na ciągach znaków. Zawiera ona dwie dane wewnętrzne: char* mpTekst i unsigned int mDlugosc. Pierwsza dana będzie przechowywać tablicę znaków na stercie, druga zawierać ilość znaków w tej tablicy. Mam utworzone trzy konstruktory - cTekst(), cTekst(const char*, unsigned int) i kopiujący cTekst(cTekst&). Przeciążam operatory '+' i '='. W pojedynkę działają dobrze, program kompiluje się bez błędów. Gdy jednak próbuję zastosować zapis a = b + c (a, b, c - obiekty cTekst) kompilator krzyczy następujący komunikat: "no match for 'operator=' in 'a = cTekst::operator+(cTekst&)(((cTekst&)(&c)))' candidates are: cTekst& cTekst::operator=(cTekst&)". Poniżej zamieszczam nagłówek i część implementacji tej klasy:
// cTekst.hpp
class cTekst
{
public:
cTekst();
cTekst(const char* tekst, unsigned int dlugosc);
cTekst(cTekst& rhs);
~cTekst();
// metody znakowe
bool PobierzZnak(unsigned int n, char& bufor); // zapisuje znak n ciągu do podanego bufora
bool ZapiszZnak(unsigned int n, const char znak); // nadpisuje n-ty znak podaną wartością
// długość
unsigned int PobierzDlugosc() const; // zwraca długość
// operatory
cTekst& operator= (cTekst& rhs);
cTekst operator+ (cTekst& rhs);
private:
char* mpTekst;
unsigned int mDlugosc; // długość tekstu bez znaku końca '\0'
};
i najistotniejsze implementacje:
// konstruktor
cTekst::cTekst() : mpTekst(0), mDlugosc(0)
{
}
// przeciążony kontruktor
cTekst::cTekst(const char* tekst, unsigned int dlugosc) : mpTekst(0), mDlugosc(0)
{
mpTekst = new char [dlugosc + 1];
for ( int i = 0; i < dlugosc; i++ )
mpTekst[i] = tekst[i];
mpTekst[dlugosc] = '\0';
mDlugosc = dlugosc;
}
// konst. kopiujący
cTekst::cTekst(cTekst& rhs)
{
mpTekst = new char [rhs.PobierzDlugosc() + 1]; // plus jedno miejsce na znak na pusty
for ( unsigned int i = 0; i < rhs.PobierzDlugosc(); i++ )
{
char bufor;
rhs.PobierzZnak(i, bufor);
mpTekst[i] = bufor;
}
// kończymy pustym znakiem
mpTekst[rhs.PobierzDlugosc()] = '\0';
mDlugosc = rhs.PobierzDlugosc();
}
// operator =
cTekst& cTekst::operator= (cTekst& rhs)
{
// jeśli adres aktualnego obiektu jest identyczny z adresem obiektu do
// którego odnosi się referencja rhs, czyli przypisujemy ten sam obiekt do
// siebie, po prostu zwracamy aktualny obiekt
if ( this == &rhs )
return *this;
__TekstBezpiecznieUsunTablice(mpTekst); // usuwamy
mpTekst = new char [rhs.PobierzDlugosc() + 1]; // alokujemy na nowo pamięć
// przepisujemy znaki
for ( int i = 0; i < rhs.PobierzDlugosc(); i++ )
{
char bufor;
rhs.PobierzZnak(i, bufor);
mpTekst[i] = bufor;
}
// kończymy psutym znakiem
mpTekst[rhs.PobierzDlugosc()] = '\0';
// przepisujemy rozmiar
mDlugosc = rhs.PobierzDlugosc();
return *this;
}
// operator+
cTekst cTekst::operator+ (cTekst& rhs)
{
unsigned int dlWyniku;
char* nowyTekst = 0;
// długość sumy ciągów znaków jest równa sumie tych długości :)
dlWyniku = mDlugosc + rhs.PobierzDlugosc();
// aklokujemy nową tablicę znaków i przepisujemy do niej ciąg z tego (this)
// obiektu i rhs
nowyTekst = new char [dlWyniku + 1];
for ( int i = 0; i < mDlugosc; i++ )
nowyTekst[i] = mpTekst[i];
for ( int i = 0; i < rhs.PobierzDlugosc(); i++ )
{
char bufor;
rhs.PobierzZnak(i, bufor);
nowyTekst[i + mDlugosc] = bufor;
}
// dodajemy na koniec zero (just in case...)
nowyTekst[dlWyniku] = '\0';
// tworzymy obiekt cTekst z tekstem uzyskanym przez proces dodawania
cTekst wynik(nowyTekst, dlWyniku);
// usuwamy zbędny bufor
delete [] nowyTekst;
nowyTekst = 0;
// zwracamy wynik
return wynik;
}
Oki, jak przebrnęliście przez powyższą sieczkę, to spox. I teraz kiedy wywala error:
cTekst proba1("Ten tekst będzie", 16);
cTekst proba2("kiedyś jednością!", 17);
cTekst proba3;
proba3 = proba1 + proba2; // tu wywala
Zdaję sobię sprawę, dlaczego kompilator zgłasza błąd - operator= pobiera jako argument referencję do cTekst a nie sam obiekt. A operator+ zwraca cTekst. Owszem, mogę zapisać to tak: cTekst& operator+ (cTekst&) i wartość zwracana zgadzałaby się z argumentem operatora =. I tak bym zrobił, gdyby nie potrzeba utworzenia nowego obiektu wewnątrz operatora +. Do lokalnej zmiennej referencji zwracać nie wolno, to wiem. Można niby utworzyć ten obiekt na stercie, ale późniejsze zwalnianie pamięci wprowadziłoby za dużo komplikacji. A powinno być prosto, zrozumiale :). Nie wiem jak ten problem rozwiązać, byłbym serdecznie wdzięczny za każdą pomoc. Btw. nie testowałem jeszcze poprawności działania operatora + (z przyczyn banalnych - nie kompiluje się), więc mogą być w nim błędy. Z tym ort! poradzę, no prob, potrzebuję tylko odpowiedzi na pytanie: jak poprawnie łączyć operatory = i +. Dzięki z góry!
ps. jak znajdziecie jakieś inne niedopatrzenia, czy znacie lepszy sposób zapisu etc. to piszcie również! thx.