Prev Next Up Title Contents Index

Olio-ominaisuudet


Seuraavassa esimerkissä toteutetaan luokkahierarkia (käytämme unkarilaista nimeämistapaa, missä c=class ja a=abstract):

Click here for Picture

Kuva . Esimerkkiohjelman oliohierarkia

piste.cpp - esimerkki perinnästä

	#include <stdio.h>
	
	// Esimerkki ehdollisesta kaantamisesta:
	#define RTTI
	// RTTI = Run Time Type Information,
	// toimii esim. BC++ 4.5 alkaen
	#ifdef RTTI
	#include <typeinfo.h>
	#endif
	
	
	//-------------------------------------------
	class caGraafinenOlio {
	protected:
	  int x,y;
	  int nakyy;
	  int paikka(int nx,int ny)
	    { x = nx; y = ny; return 0;             }
	public:
	  caGraafinenOlio(int ix=0, int iy=0)
	    { paikka(ix,iy); nakyy = 0;             }
	  virtual ~caGraafinenOlio() { }
	  virtual int piirra() const = 0;
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	  int nakyvissa() const { return nakyy;     }
	  int sammuta();
	  int sytyta();
	  int siirra(int nx, int ny) {
	    if ( !nakyvissa() ) return paikka(nx,ny);
	    sammuta(); paikka(nx,ny); return sytyta();
	  }
	
	
	
	
	  virtual int tulosta(const char *s="")
	   const {
	#   ifdef RTTI
	    printf("%-10s: ",typeid(*this).name());
	#   endif
	    printf("%-10s (%02d,%02d)",s,x,y);
	    return 0;
	  }
	}; // caGraafinen olio
	
	int caGraafinenOlio::sammuta()
	{
	  if ( !nakyvissa() ) return 1;
	  printf("Sammutettu: ");
	  nakyy = 0;
	  return piirra();
	}
	
	int caGraafinenOlio::sytyta()
	{
	  if ( nakyvissa() ) return 1;
	  printf("Sytytetty:  ");
	  nakyy = 1;
	  return piirra();
	}
	
	//-------------------------------------------
	class caSateellinenOlio :
	  public caGraafinenOlio {
	protected:
	  int r;
	  int koko(int nr) { r = nr; return 0;      }
	public:
	  caSateellinenOlio(int ix=0,int iy=0,
	                    int ir=1) :
	    caGraafinenOlio(ix,iy), r(ir) {}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	  virtual int tulosta(const char *s="")
	  const {
	    caGraafinenOlio::tulosta(s);
	    printf( " r=%d",r);
	    return 0;
	  }
	  int muuta_koko(int nr) {
	    if ( !nakyvissa() ) return koko(nr);
	    sammuta(); koko(nr); return sytyta();
	  }
	}; // caSateellinen olio
	
	
	
	
	//-------------------------------------------
	class cPiste : public caGraafinenOlio {
	public:
	  cPiste(int ix=0, int iy=0) :
	    caGraafinenOlio(ix,iy) {}
	  virtual ~cPiste() { sammuta(); }
	  virtual int piirra() const {
	   tulosta("Piste"); printf("\n"); return 0;}
	};
	
	//-------------------------------------------
	class cYmpyra : public caSateellinenOlio {
	public:
	  cYmpyra(int ix=0, int iy=0, int ir=1) :
	    caSateellinenOlio(ix,iy,ir) {}
	  virtual ~cYmpyra() { sammuta(); }
	  virtual int piirra() const {
	   tulosta("Ympyra"); printf("\n"); return 0;}
	};
	
	
	int main(void)
	{
	  caGraafinenOlio *p;
	  caGraafinenOlio *kuvat[10];
	  int i;
	  cPiste p1,p2(10,20);
	  cYmpyra y1(1,1,2);
	  p1.sytyta(); p2.sytyta();
	  p1.siirra(7,8);
	  y1.sytyta(); y1.muuta_koko(5);
	
	  // Esimerkki polymorfismista
	  p = new cYmpyra(9,9,9);
	  p->sytyta(); p->siirra(8,8);
	  // p->muuta_koko(4); ei laillinen
	# ifdef RTTI
	//  if ( typeid(*p) == typeid(cYmpyra) )
	  caSateellinenOlio *ps =
	    dynamic_cast<caSateellinenOlio *>(p);
	  if ( ps ) ps->muuta_koko(4);
	# else
	  ((caSateellinenOlio *)p)->muuta_koko(4);
	# endif
	  delete p;
	
	  // Esimerkki polymorfismista
	  kuvat[0] = new cYmpyra(10,10,100);
	  kuvat[1] = new cPiste(11,11);
	  kuvat[2] = new cYmpyra(12,12,102);
	  kuvat[3] = NULL;
	  for (i=0; kuvat[i];i++) kuvat[i]->sytyta();
	  for (i=0; kuvat[i];i++) delete kuvat[i];
	
	  return 0;
	}

piste.dpr - esimerkki perinnästä

	program piste;
	
	{ Esimerkki ehdollisesta kaantamisesta: }
	{$DEFINE RTTI }
	
	uses
	  WinCRT,SysUtils;
	
	
	
	
	{-------------------------------------------}
	type caGraafinenOlio = class
	protected
	  x,y:integer;
	  nakyy:boolean;
	  procedure paikka(nx,ny:integer);
	public
	  constructor Create;
	  constructor Create2(ix,iy:integer);
	  destructor Destroy; override;
	  procedure piirra; virtual; abstract;
	  function nakyvissa:boolean;
	  procedure sammuta;
	  procedure sytyta;
	  procedure siirra(nx,ny:integer);
	  procedure tulosta(s:string); virtual;
	end;
	
	procedure caGraafinenOlio.paikka(
	                              nx,ny:integer);
	begin x := nx; y := ny; end;
	
	constructor caGraafinenOlio.Create2(
	                              ix,iy:integer);
	begin
	  inherited Create;
	  paikka(ix,iy);
	  nakyy := False;
	end;
	
	constructor caGraafinenOlio.Create;
	begin Create2(0,0); end;
	
	destructor caGraafinenOlio.Destroy;
	begin  sammuta;
	  inherited Destroy;
	end;
	
	function caGraafinenOlio.nakyvissa:boolean;
	begin Result := nakyy; end;
	
	procedure caGraafinenOlio.siirra(
	                              nx,ny:integer);
	begin
	  if ( not nakyvissa ) then begin
	    paikka(nx,ny); exit;
	  end;
	  sammuta; paikka(nx,ny); sytyta;
	end;
	
	procedure caGraafinenOlio.tulosta(s:string);
	begin
	  {$IFDEF RTTI}
	  write(format('%-10s: ',[ClassName]));
	  {$ENDIF}
	  write(format('%-10s (%02d,%02d)',[s,x,y]));
	end;
	
	procedure caGraafinenOlio.sammuta;
	begin
	  if ( not nakyvissa ) then exit;
	  write('Sammutettu: ');
	  nakyy := False;
	  piirra;
	end;
	
	procedure caGraafinenOlio.sytyta;
	begin
	  if ( nakyvissa ) then exit;
	  write('Sytytetty:  ');
	  nakyy := True;
	  piirra;
	end;
	
	{-------------------------------------------}
	type caSateellinenOlio =
	  class(caGraafinenOlio)
	protected
	  r:integer;
	  procedure koko(nr:integer);
	public
	  constructor Create3(ix,iy,ir:integer);
	  constructor Create2(ix,iy:integer);
	  constructor Create;
	  procedure tulosta(s:string); override;
	  procedure muuta_koko(nr:integer);
	end;
	
	procedure caSateellinenOlio.koko(nr:integer);
	begin r := nr; end;
	
	constructor caSateellinenOlio.Create3(
	                           ix,iy,ir:integer);
	begin
	  inherited Create2(ix,iy);
	  koko(ir);
	end;
	
	constructor caSateellinenOlio.Create2(
	                              ix,iy:integer);
	begin Create3(ix,iy,1); end;
	
	constructor caSateellinenOlio.Create;
	begin inherited Create; koko(1); end;
	
	procedure caSateellinenOlio.tulosta(s:string);
	begin
	  inherited tulosta(s);
	  write(' r=',r);
	end;
	
	procedure caSateellinenOlio.muuta_koko(
	                                 nr:integer);
	begin
	  if ( not nakyvissa ) then begin
	    koko(nr); exit;
	  end;
	  sammuta; koko(nr); sytyta;
	end;
	
	{-------------------------------------------}
	type cPiste = class(caGraafinenOlio)
	public
	  procedure piirra; override;
	end;
	
	procedure cPiste.piirra;
	begin tulosta('Piste'); writeln; end;
	
	{-------------------------------------------}
	type cYmpyra = class(caSateellinenOlio)
	public
	  procedure piirra; override;
	end;
	
	procedure cYmpyra.piirra;
	begin tulosta('Ympyra'); writeln; end;
	
	{-------------------------------------------}
	var p     : caGraafinenOlio;
	    kuvat : array[0..9] of caGraafinenOlio;
	    p1,p2 : cPiste;
	    y1    : cYmpyra;
	    i     : integer;
	begin
	  p1 := cPiste.Create;
	  p2 := cPiste.Create2(10,20);
	  y1 := cYmpyra.Create3(1,1,2);
	  p1.sytyta;  p2.sytyta;
	  p1.siirra(7,8);
	  y1.sytyta; y1.muuta_koko(5);
	
	  (* Esimerkki polymorfismista             *)
	  p := cYmpyra.Create3(9,9,9);
	  p.sytyta; p.siirra(8,8);
	  { p.muuta_koko(4);  ei laillinen }
	  {$IFDEF RTTI }
	  if ( p is caSateellinenOlio ) then
	  {$ENDIF}
	  (p as caSateellinenOlio).muuta_koko(4);
	  p.Free;
	
	  (* Esimerkki polymorfismista             *)
	  kuvat[0] := cYmpyra.Create3(10,10,100);
	  kuvat[1] := cPiste.Create2(11,11);
	  kuvat[2] := cYmpyra.Create3(12,12,102);
	  kuvat[3] := NIL;
	  i:=0;
	  while ( kuvat[i] <> NIL ) do begin
	    kuvat[i].sytyta; inc(i);
	   end;
	  i:=0;
	  while ( kuvat[i] <> NIL ) do begin
	    kuvat[i].Free; inc(i);
	   end;
	
	  y1.Free;  p2.Free;  p1.Free;
	end.

Mikäli vakio RTTI on määritelty, tulostavat molemmat ohjelmat:

	Sytytetty:  cPiste    : Piste      ( 0, 0)
	Sytytetty:  cPiste    : Piste      (10,20)
	Sammutettu: cPiste    : Piste      ( 0, 0)
	Sytytetty:  cPiste    : Piste      ( 7, 8)
	Sytytetty:  cYmpyra   : Ympyra     ( 1, 1) r=2
	Sammutettu: cYmpyra   : Ympyra     ( 1, 1) r=2
	Sytytetty:  cYmpyra   : Ympyra     ( 1, 1) r=5
	Sytytetty:  cYmpyra   : Ympyra     ( 9, 9) r=9
	Sammutettu: cYmpyra   : Ympyra     ( 9, 9) r=9
	Sytytetty:  cYmpyra   : Ympyra     ( 8, 8) r=9
	Sammutettu: cYmpyra   : Ympyra     ( 8, 8) r=9
	Sytytetty:  cYmpyra   : Ympyra     ( 8, 8) r=4
	Sammutettu: cYmpyra   : Ympyra     ( 8, 8) r=4
	Sytytetty:  cYmpyra   : Ympyra     (10,10) r=100
	Sytytetty:  cPiste    : Piste      (11,11)
	Sytytetty:  cYmpyra   : Ympyra     (12,12) r=102
	Sammutettu: cYmpyra   : Ympyra     (10,10) r=100
	Sammutettu: cPiste    : Piste      (11,11)
	Sammutettu: cYmpyra   : Ympyra     (12,12) r=102
	Sammutettu: cYmpyra   : Ympyra     ( 1, 1) r=5
	Sammutettu: cPiste    : Piste      (10,20)
	Sammutettu: cPiste    : Piste      ( 7, 8)
Jos vakiota RTTI ei ole määritelty, on tulostus muuten sama, mutta puuttuu sarake, jossa on cPiste ja cYmpyra.

Delphissä on kaksi tapaa tehdä luokkia:

Tässä monisteessa käytetään pääasiassa vain class- määreellä esiteltyjä luokkia
	// Vertaa:
	int siirra(int nx, int ny) {
	  if ( !nakyvissa() ) return paikka(nx,ny);
	  sammuta(); paikka(nx,ny); return sytyta();
	}
	
	// Tai:
	void siirra(int nx, int ny) {
	  if ( !nakyvissa() ) { paikka(nx,ny); return; }
	  sammuta(); paikka(nx,ny); sytyta();
	}
	{ Vertaa: }
	function caGraafinenOlio.siirra(nx,ny:integer):integer;
	begin
	  if ( not nakyvissa ) then begin siirra := paikka(nx,ny); exit;  end;
	  sammuta; paikka(nx,ny); siirra := sytyta;
	end;
	
	{ Tai: }
	procedure caGraafinenOlio.siirra(nx,ny:integer);
	begin
	  if ( not nakyvissa ) then begin paikka(nx,ny); exit;  end;
	  sammuta; paikka(nx,ny); sytyta;
	end;
	

Tehtävä 2.15 C++ ilman inline-funktoita

Kirjoita piste.cpp käyttämättä inline- funktioita

Tehtävä 2.16 Neliö ja suorakaide

Lisää kumpaankin esimerkkiin (piste.cpp ja piste.dpr) luokka cNelio.
Entä cSuorakaide?

Tehtävä 2.17 Väri ja suunta

Mieti miten luokkahierarkiaa muutetaan, mikäli kuvioista halutaan värillisiä ja eri asennossa olevia.


Prev Next Up Title Contents Index