Prev Next Up Title Contents Index

Operaattori- funktiot


C++ - kielessä voidaan myös operaattoreita lisämääritellä. Huomattakoon, että vaikka operaattoreille annetaankin "uusia merkityksiä", säilyy niiden precedenssi ennallaan. Lisäksi operaattoreiden määrittelyssä tulee olla tarkkana, jotta säilyttää niiden "alkuperäisen" tarkoituksen. Eli ei ole suotavaa määritellä esimerkiksi operaattoria (miinus) - joka tekee jotakin yhdistämiseen liittyvää.

Esimerkiksi kahden pisteen yhteenlaskussa olisi mielekästä laskea yhteen pisteen x-koodinaatit ja pisteen y-koordinaatit. Samoin tietenkin pisteiden vähennyslaskussa (vrt. vektorit).

operato1.cpp - operaattoreiden kuormittaminen

	/* OPERATO1.CPP */
	// Esimerkki Operaatoreiden kuormittamisesta
	// Huomatus!  Esimerkkin operattorit eivät välttämättä muodosta
	// kunnon "algebraa"
	#include <stdio.h>
	#include <math.h>
	
	
	class cPaikka {
	  int x,y;
	public:
	  void tulosta() const                     {printf("(%d,%d)\n",x,y);}
	  void aseta(int nx,int ny)                { x=nx; y=ny;            }
	  cPaikka(int ix=0, int iy=0)              { aseta(ix,iy);          }
	  cPaikka operator+(const cPaikka &p2);    // p3 = p1 + p2, vrt. p3 = +(p1,p2)
	  cPaikka operator-(const cPaikka &p2);    // p3 = p1 - p2;
	  cPaikka operator+=(const cPaikka &p2);   // p1 += p2;
	  cPaikka &operator=(int i);               // p1 = i;
	  cPaikka &operator=(const cPaikka &p2);   // p3 = p2;
	  cPaikka &operator++();                   // ++p
	  cPaikka operator++(int i);               // p1++ (i=0)
	  cPaikka &operator+=(int i);              // p1 += 5;
	  operator double() const {return sqrt(x*x+y*y);} // d  = p1;
	  operator int()    const {return x;            } // i  = p1;
	  friend int operator+(int i, const cPaikka &p);  // i  = 5 + p;
	};
	
	cPaikka cPaikka::operator+(const cPaikka &p2)
	{
	  cPaikka t;
	  t.x = x + p2.x;
	  t.y = y + p2.y;
	  return t;
	}
	
	cPaikka cPaikka::operator-(const cPaikka &p2)
	{
	  cPaikka t;
	  t.x = x - p2.x;
	  t.y = y - p2.y;
	  return t;
	}
	
	cPaikka cPaikka::operator+=(const cPaikka &p2)
	{
	  x += p2.x;
	  y += p2.y;
	  return *this;
	}
	
	cPaikka &cPaikka::operator=(int i)
	{
	  x = i; y = 0;
	  return *this;
	}
	
	cPaikka &cPaikka::operator=(const cPaikka &p2)
	{
	  x = p2.x; y = p2.y;
	  return *this;
	}
	
	cPaikka &cPaikka::operator++()           // ++p
	{
	  x++;
	  return *this;
	}
	
	cPaikka cPaikka::operator++(int /* i */) // p++
	{
	  cPaikka t(*this);
	  x++;
	  return t;
	}
	
	cPaikka &cPaikka::operator+=(int i)
	{
	  x += i;
	  return *this;
	}
	
	int operator+(int i, const cPaikka &p)
	{
	  return i + p.x;
	}
	
	
	int main(void)
	{
	  cPaikka p1(2,2),p2(1,4),p3;
	  p3 = p1 + p2;     p3.tulosta();  // (3,6)
	  p3 = p3 - p1;     p3.tulosta();  // (1,4)
	                    p2.tulosta();  // (1,4)
	  p3 = p1;          p3.tulosta();  // (2,2)
	  p3 = 9;           p3.tulosta();  // (9,0)  // jollei = -määritystä, kutsuisi
	                                             // rakentajaa cPaikka(9)
	  p3 += p2;         p3.tulosta();  // (10,4)
	  ++p2;             p2.tulosta();  // (2,4)
	  p2++;             p2.tulosta();  // (3,4)
	  p2+=4;            p2.tulosta();  // (7,4)
	
	  int i;
	  i = 4+p2;         printf ("i=%d\n",i);     // 11 // Ilman friend-funktiota ei
	                                                   // saisi näin päin
	  i = p3;           printf ("i=%d\n",i);     // 10
	  double d = p3;    printf ("d=%3.2lf\n",d); // 10.77
	  return 0;
	}
Aina ei ole ilmeistä kannattaako operaattori esitellä luokan jäsenfunktioksi (metodiksi) vaiko ystäväfunktioksi. Esimerkiksi yhteenlasku olisi voitu tehdä myös:
	class cPaikka...
	  friend cPaikka operator+(cPaikka &p1,cPaikka &p2); // p3 = p1 + p2
	}; // cPaikka
	
	cPaikka operator+(cPaikka &p1,cPaikka &p2)  // Tätä kutsutaan edelleen p3=p1+p2
	{
	  cPaikka t;
	  t.x = p1.x + p2.x;
	  t.y = p1.y + p2.y;
	  return t;
	}

Tehtävä 1.28 Miksi sijoituksen määrittely

Miksi operato1.cpp:ssä on täytynyt lisämääritellä sijoitus piste=piste samalla kun on lisätty muunnos (int)p tai (double)p? (Vihje: Kokeile poistaa sijoitus ja päättele mikä menee väärin ja miksi; vaikkapa ajamalla askel kerrallaan debuggerilla).

Tehtävä 1.29 Ylimääräiset muuttujat operaattoreissa

Tee ohjelman operato2.cpp tehtävät.

Tehtävä 1.30 Lisää operaatiota

Lisää ohjelmaan operato1.cpp seuraavat:
1.
Kirjoita samaan tiedostoon pisteelle itseisarvofunktio, jota voidaan kutsua fabs(p);
2.
Tee vertailuoperaattori ==, joka vertaa kahta pistettä.
3.
Määrittele -= - operaattori vähentämään pistettä pisteellä.
4.
Määrittele pisteelle etumerkinvaihto operaattori -. (mitä ko. oper. palauttaa?)
5.
Kirjoita vielä + operaattori, jolloin +p muuttaa p:n kaikki koordinaatit positiivisiksi (onko ko. operaattori oikeasti järkevä ja miksi on tai ei?).

Tehtävä 1.31 Luokka 2x2 matriiseille

Kirjoita luokka 2x2 matriiseille. Laita luokkaan "riittävä" määrä operaattoreita. Kuinka helppoa luokka olisi modifioida yleiseksi nxn matriiseja käsitteleväksi luokaksi? Entäpä nxm?


Prev Next Up Title Contents Index