Operatory
description
Transcript of Operatory
OOP C++ - operatory 1
Operatory
class complex {private:
double re, im;public:
complex (double r, double i = 0) { re = r; im = i; }friend complex operator+ (complex, complex);friend complex operator*(complex, complex);complex& operator += (complex);
};
void f(){
complex a = complex (1.3, 4);complex b = complex(3);complex c(0);
c = b + a;c = b+c * a;c = b + 10; // poprawne - nastąpi niejawna konwersja
}
Można definiować operatory dla:
+ - * / % & | ! itd.= < > += itd.<< >> && || ++ -- itd.[ ] ( ) new delete
Nie można zmienić arności ani priorytetów operatorów.
Operatory są z definicji przeciążone.
OOP C++ - operatory 2
Zasada: operator musi mieć co najmniej 1 argument będący obiektem klasy (nie dotyczy new i delete).Zwykle operator jest albo funkcją składową jakiejś klasy, albo jej funkcją zaprzyjaźnioną.
Niech @ będzie dwuargumentowym operatorem. Musi być albojednoargumentową funkcją składową (niejawnym pierwszymargumentem jest obiekt, w którym wykonywana jest metoda),albo dwuargumentową funkcją zaprzyjaźnioną (pierwszy argument jest jawny).
a @ b jest interpretowane jako a.operator@ (b)lub operator@ (a, b)
Jeśli @ jest jednoargumentowym operatorem, to @ a jest interpretowane jako a.operator@ () lub operator@ (a)
complex operator+ (complex a, complex b){
return complex (a.re + b.re, a.im + b.im);}// i analogicznie operator*
inline complex& complex::operator+= (complex a){
re += a.re;im += a.im;return *this;
}
OOP C++ - operatory 3
Przeciążenie operatora <<
class ostream {// ....public:
ostream& operator<< (char*);ostream& operator<< (int i);// ...
};
Możemy przeciążyć ten operator. Na przykład:
class complex {private:
double re, im;public:
// ....friend ostream& operator<< (ostream& os, complex& c);
};
ostream& operator<< (ostream& os, complex& c){
os << “(“ << c.re << “,“ << c.im << “)”;return os;
}
Można teraz napisać:
complex c = complex (3.5, 6.7);cout << c;
Uwaga: operator << nie może być metodą klasy complex, ponieważ jego pierwszym argumentem ma być strumień, a nie obiekt complex.
OOP C++ - operatory 4
Przeciążanie operatora [ ]
Wyrażenie x [ i ] jest interpretowane jako x . operator [ ] ( i ). Operator [ ] musi być funkcją składową.
Przykład: dynamiczna tablica indeksowana napisami, służąca do zliczania słów z pliku (coś w rodzaju słownika, o kluczach będących napisami i wartościach będących liczbami).
struct pair {char *index;int val;
};
class assoc_array {private:
::pair *vec; // tablica par, :: bo w std też jest pairint max, free; // free - pierwsze wolne miejsce
public:assoc_array (int); // konstruktorint& operator [ ] (char *); // ma dać drugi element paryvoid print_all ( );
};
assoc_array :: assoc_array (int s){
max = (s > 16) ? s : 16;free = 0;vec = new ::pair[max];
}
Przykład użycia:char buf [MAX];assoc_array table (512);
while (cin >> word) table [word] +; // table[word] jest referencją do val
OOP C++ - operatory 5
int& assoc_array :: operator [ ] (char *s)// Szuka pary o kluczu p; jeśli nie ma, to tworzy. Zwraca referencję do// wartości (drugiego elementu pary){
::pair *pp;
for (pp = &vec [free-1]; vec <= pp; pp--)if (strcmp (s, pp -> index) == 0) return (pp -> val);
if (free == max ) // przepełnienie{
::pair* nvec = new ::pair [max * 2];
for (int i = 0; i < max; i++)nvec [ i ] = vec [ i ];
delete[] vec;vec = nvec;max = 2 * max;
}pp = &vec [free ++];pp -> index = new char [strlen (s) + 1];strcpy ( pp -> index, s);pp -> val = 0;return (pp -> val);
}
void assoc_array :: print_all (){
for (int i = 0; i < free; i++)cout << endl << vec [i].index << “: “ << vec [i].val;
}
OOP C++ - operatory 6
Przeciążanie operatora ()
Jest to przeciążenie wywoływania funkcji, czyli wyrażenia postaci wyr (lista_wyr)gdzie wyr jest pierwszym argumentem operatora (), a lista_wyr drugim.
Przykład - iterator dla assoc_array.
Do deklaracji klasy assoc_array dodajemy
friend class iterator_assoc;
class iterator_assoc {private:
const assoc_array& tab; // iterowana tablicaint i; // bieżący indeks
public:iterator_assoc (const assoc_array& s) : tab(s) { i = 0; }::pair* operator () () // operator ()
{ return (i < tab.free) ? &tab.vec[i++] : 0; }};
main () // program liczy liczbę wystąpień słów na wejściu{
const MAX = 256;char buf [MAX];assoc_array liczniki (512);
while (cin >> buf) liczniki [buf]++;
iterator_assoc nast (liczniki); // inicjalizacja iteratora::pair * p;while (p = nast () )
cout << p -> index << “: “ << p -> val << endl;}
OOP C++ - operatory 7
Konwersje typów - operatory konwersji
X :: operator T () definiuje konwersję z X do T
class String {public:
.....operator char* () { return tablica; }
private:char* tablica; int dlugosc;
};String s = ...;char *p = s; // konwersja z typu String do char*
Przeciążanie operatora =
Problem ten sam, co z konstruktorem kopiującym.
class Napis{ private:
char *ptr; size_t len; public:
Napis () { ptr = NULL; len = 0; } // konstruktor kopiujący:Napis (const Napis& n ) {ptr = strdup(n.ptr); len = strlen(ptr);}Napis& operator= (const Napis& n);virtual ~Napis () { /*if (ptr != NULL)*/ delete ptr; }
};
Napis& Napis :: operator= (const Napis& n){ if (this != &n)
{ delete ptr;ptr = new char [len = n.len];strcpy (ptr, n.ptr);
}return *this;
}
OOP C++ - operatory 8
class String {public:// Konstruktory/Destruktory
String() {character_array = new char[1]; character_array[0] = '\0';}
String(char* new_string);String(String& new_string); // konstruktor kopiującyString(int integer_to_convert);String(float float_to_convert);~String() { }
// Funkcje implementujące operacjesize_t size() {return string_length;}String& copy();int as_integer();float as_float();String& read_up_to (char delimiter);String& break_at (char delimiter);bool contains_string (char* a_character_array);int locate_string (char* a_character_array);String& copy_sequence (int sequence_start, int sequence_end);
// OperatoryString& operator+ (String& a_string);String& operator+= (String& a_string);String& operator= (String& a_string);String& operator= (const char* a_character_array);int operator< (String& a_string);int operator> (String& a_string);int operator== (String& a_string);
operator char* () {return character_array; } // konwersjafriend ostream& operator<< (ostream& os, String& a_string);
private:char* character_array;size_t string_length;
};
OOP C++ - operatory 9
String& String::operator+ (String& a_string){
size_t total_size = string_length + strlen(a_string) + 1;char* temp_array = new char[total_size];char* char_array = a_string;
strcpy(temp_array, character_array);strcat(temp_array, char_array);String* new_string = new String(temp_array);delete temp_array;return *new_string;
}
String& String::operator= (String& a_string){
char* new_char_array = a_string;delete character_array;character_array = new char[strlen(new_char_array) + 1];strcpy(character_array, new_char_array);string_length = strlen(character_array);return *this;
}
String& String::operator= (const char* a_character_array){
delete character_array;character_array = new char[strlen(a_character_array) + 1];strcpy(character_array, a_character_array);string_length = strlen(character_array);return *this;
}
int String::operator==(String& a_string){ return(strcmp(character_array, (char*) a_string) == 0); }
ostream& operator<< (ostream& os, String& a_string){ os << a_string.character_array; return os;}
OOP C++ - operatory 10
String::String(char* new_string)
{
character_array = strdup(new_string);
string_length = strlen(character_array);
}
OOP C++ - operatory 11
Niebezpieczna czwórka
• Konstruktor bezargumentowy
• Konstruktor kopiujący
• Destruktor
• Operator przypisania