C++ preklapanje operatora

iron king

Početnik
Poruka
7
Pozdrav

Imam pitanje u vezi sintakse pri preklapanju.

Naime kada pravimo obicnu String klasu ( char *str,int len ) obicno se definisu i operatori koji je prate da bismo je lakse koristili.Skontao sam sva preklapanja sem operatora [].

oni se uvek preklapaju kolko vidim ovako
Kod:
char &operator[](int i ) {return str[i]};
char operator[](int i) const {return str[i]};

U knjizi pise da jedan sluzi za citanje a drugi za pisanje karaktera,mada meni nije jasno kako.Kontam o ovaj sa const je za citanje jer ga ne menja.Buni me taj znak za adresu & ispred operatora, ne znam sta radi.Da li se u gornjem slucaju vraca adresa i-og karaktera string(i kako se to korsiti za pisanje)?
 
Nije to znak za adresu vec upucivac (pogledaj sta su upucivaci u C++).

I takodje ne pise se:
char &operator[]

Vec:
char& operator[]

Takodje funkcija operator[] zapravo sluzi da kad imamo niz objekata neke klase, mozemo da im pristupamo sa obj ,gde je obj instanca neke klase Objekat (Objekat obj), slicno kao da se radi o prostim tipovima podataka

Tako da pravi primer za preklapanje operatora [] bi bio:

Objekat& operator[] (int i) {...}, kasnije tom objektu mozes da pristupas sa obj[1], obj[2]....

A mozes i da dodeljujes vrednosti obj[1]=obj[2], zato je bitno da vrednost operatorske funkcije bude upucivac na neki tip, a ne sam tip (pogledaj i sta su lvrednosti u c++);

Sto se tice ove funkcije za citanje, najveca razlika je ovo const, to joj daje neku vrstu bezbednosti da objekat iz koga se poziva nece biti menjan, i takodje njemu nikad nece biti dodeljivana vrednost zato povratna vrednost ne mora da bude upucivac na tip (mada moze i ja licno uvek tako pisem, tako su me i ucili)
 
Kod:
char &operator[](int i ) {return str[i]};
char operator[](int i) const {return str[i]};

U knjizi pise da jedan sluzi za citanje a drugi za pisanje karaktera,mada meni nije jasno kako.Kontam o ovaj sa const je za citanje jer ga ne menja.Buni me taj znak za adresu & ispred operatora, ne znam sta radi.Da li se u gornjem slucaju vraca adresa i-og karaktera string(i kako se to korsiti za pisanje)?

U principu, umesto ovoga mogao bi da definises svoje metode (gettere i settere) kako bi menjao atribute objekta. U ovom slucaju bi manipulisao sa znakovnom niskom koja se cuva unutar objekta.
Ali C++ ti, u ovom slucaju, omogucava mnogo lepsi zapis ovoga, uz pomoc preklapanja operatora [] za indeksiranje. Mozes da definises sta znaci indeksirati instancu tvoje klase (u ovom slucaju ces pristupati odgovarajucim karakterima unutar niske koja se cuva u objektu).

Kod:
char &operator[](int i ) {return str[i]};

Operator [] mozes da posmatras kao binarni operator (objekat [] broj). Levi operand ovog operatora bi bio upravo objekat koji je pozvao ovaj operator (this), a desni operand je broj koji se zadaje kao argument.
Ovo ce ti mozda biti jasnije kad vidis da ovo:
objekat[j]
mozes da zapises kao:
objekat.operator[](j)

Znaci, videli smo da je ovo zapravo binarna operacija. Dobro, sta je onda rezultat ove binarne operacije? Ovo prvo ce da vrati referencu na odredjeni karakter tako da kad napises sledece:

objekat = 'a';

sa leve strane dodele ces imati referencu na karakter (sto je validno). Dakle sa leve strane imas char& a sa desne strane char, tako da ovde zapravo manipulises sa referencom.
Cak mislim da bi bilo dovoljno definisati samo ovaj prvi jer bi on mogao da se pojavi sa obe strane operatora dodele.

Kod:
char operator[](int i) const {return str[i]};

Izgleda dosta slicno, ali ipak se dosta razlikuje. Pre svega, povratna vrednost je char. Dakle, vratice se neki karakter, koji ne moze da bude leva strana operatora dodele (lvalue).
Kvalifikator const kaze da objekat nad kojim je pozvan operator nece biti izmenjen.

Rezime:
Ukoliko preklopis operator prvom fjom, omogucavas da se to nadje i sa leve i sa desne strane operatora dodele (referenca moze da bude i lvalue i rvalue).
Posto vracas referencu, omogucavas izmenu odredjenog karaktera na koji dobijas referencu.

Ukoliko preklopis drugom fjom, vraca se char i time omogucavas da se u izrazu nadje samo sa desne strane operatora dodele (rvalue).

----------------------------------
EDIT:
----------------------------------

Evo i jedan primer:

string.h
Kod:
#ifndef moj_string_
#define moj_string_

class MojString
{
	public:
		//konstruktori
		MojString(const char*);
		
		//desktruktor
		~MojString();
		
		//operatori
		char& operator[](int) const;
		
		//metodi
		int duzina() const;
	
	private:
		char *m_string;
		int m_duzina;
		
		friend std::ostream& operator<<(std::ostream&, const MojString&);
};

std::ostream& operator<<(std::ostream&, const MojString&);

#endif

string.cpp
Kod:
#include <cstring>
#include <iostream>
#include "string.h"

MojString::MojString(const char *str)
{
	m_duzina = strlen(str);
	m_string = new char[m_duzina + 1];
	strcpy(m_string, str);
}

MojString::~MojString()
{
	delete [] m_string;
}

int MojString::duzina() const
{
	return m_duzina;
}

std::ostream& operator<<(std::ostream &out, const MojString &s)
{
	out << s.m_string;
	return out;
}

char& MojString::operator[](int indeks) const
{
	return m_string[indeks];
}

main.cpp
Kod:
#include <iostream>
#include "string.h"

int main()
{
	MojString s1("proba");
	std::cout << s1 << " testiranje " << s1 << std::endl;
	s1[1] = s1[1] + 1;
	std::cout << s1 << " testiranje " << s1 << std::endl;
	return 0;
}

Ukoliko stavis da operator ne vraca referencu, videces da ces dobiti gresku oblika:
Kod:
error: lvalue required as left operand of assignment s1[1] = s1[1] + 1;
 
Poslednja izmena:
Hvala puno! :)

Nisam siguran iz koje je knjige, ali u principu svaka klasa koja kao atribut sadrzi neki niz i potrebno mu je nekako pristupati iz spoljasnjosti programa je pogodnija za preopterecivanje tog operatora nego za pisanje gettera i settera za to, jer ovako dobijas mnogo pregledniji kod :)
 

Back
Top