Tomasz Marks - Wydział MiNI PW
-1-
Programowanie Obiektowe
(j
ę
zyk C++)
Wykład 5.
Tomasz Marks - Wydział MiNI PW
-2-
Projekt klasy
Vector
Tomasz Marks - Wydział MiNI PW
-3-
Projekt klasy Vector – zało
ż
enia
1 – Ma opisywa
ć
wektory o ró
ż
nych rozmiarach.
2 – Składowe przechowywane w dynamicznie alokowanej tablicy.
3 – Mo
ż
liwo
ść
tworzenia wektorów o domy
ś
lnie ustalanym rozmiarze.
4 – Wszystkie pola prywatne, dost
ę
pne jedynie za pomoc
ą
odpowiednich metod.
5 – Obliczanie normy euklidesowej.
6 – Realizacja operacji arytmetyki wektorów.
7 – Strumieniowe operacje we/wy.
Tomasz Marks - Wydział MiNI PW
-4-
Projekt klasy Vector – plik definicyjny [1]
// vector.h
#ifndef DEFINE_FOR_THE_FIRST_INCLUSION_OF_VECTOR_H
#define DEFINE_FOR_THE_FIRST_INCLUSION_OF_VECTOR_H
#include <iostream>
using namespace std;
#define VECTOR_DEF_SIZE 3
class Vector
{
………………………….
………………………….
………………………….
};
#endif
Tomasz Marks - Wydział MiNI PW
-5-
Projekt klasy Vector – plik definicyjny [2]
// vector.h
#pragma once
#include <iostream>
using namespace std;
#define VECTOR_DEF_SIZE 3
class Vector
{
………………………….
………………………….
………………………….
};
Tomasz Marks - Wydział MiNI PW
-6-
Projekt klasy Vector – plik definicyjny [3]
class Vector
{
int Size;
double *V;
static int DefSize;
void Init ( int size=0, double val=0, double *arr=0 );
public:
Vector ();
Vector ( int size, double val = 0 );
Vector (int size, double arr[ ] );
Vector ( const Vector& arg );
~Vector ( );
static void setDefSize ( int newDS );
static int getDefSize ( );
int getSize ( ) const;
double Norm ( ) const;
………………………….
Tomasz Marks - Wydział MiNI PW
-7-
Projekt klasy Vector – plik definicyjny [4]
………………………….
double getAt ( int i ) const;
void setAt ( int i, double val );
double& operator [ ] ( int i );
Vector& operator = ( const Vector& rhs );
Vector& operator += ( const Vector& b );
Vector& operator -= ( const Vector& b );
friend Vector operator + ( const Vector& a, const Vector& b );
friend Vector operator - ( const Vector& a, const Vector& b );
friend Vector operator * ( double k, const Vector& a );
friend double operator * ( const Vector& a, const Vector& b );
friend istream& operator >> ( istream& inp, Vector& vec );
friend ostream& operator << ( ostream& out, const Vector& vec );
………………………….
};
Tomasz Marks - Wydział MiNI PW
-8-
Składowe statyczne [1]
class Vector
{
………………………….
static int DefSize;
………………………….
static void setDefSize ( int newDS );
static int getDefSize ( );
………………………….
};
Statyczne składowe (pola i metody) nie wymagaj
ą
istnienia jakiegokolwiek
obiektu klasy, w której s
ą
zdefiniowane.
Pola statyczne stanowi
ą
"wspóln
ą
pami
ęć
" wszystkich obiektów danej klasy
i nie s
ą
w nich reprezentowane (rozmiar obiektu jest okre
ś
lony przez sum
ę
rozmiarów pól niestatycznych).
Metody statyczne mo
ż
na uwa
ż
a
ć
za zwykłe funkcje, tyle
ż
e zdefiniowane w klasie
i przeznaczone głównie do przetwarzania pól statycznych.
Tomasz Marks - Wydział MiNI PW
-9-
Projekt klasy Vector – implementacje [1]
// vector.cpp
#include <math>
#include "vector.h"
#define VECTOR_DEF_SIZE 3
int Vector::DefSize = VECTOR_DEF_SIZE;
// UWAGA! UWAGA! UWAGA!
// pole statyczne DefSize musi by
ć
zdefiniowane
// n.p. w pliku implementacyjnym klasy
…………………………………………………………...
……… implementacje (definicje) ………………….
……… metod klasy …………………………………..
……… i funkcji zaprzyja
ź
nionych z klas
ą
….…….
…………………………………………………………...
Tomasz Marks - Wydział MiNI PW
-10-
Projekt klasy Vector – implementacje [2]
// metoda prywatna
void Vector :: Init ( int s, double val, double tab[ ] )
{
if ( s <= 0 ) s = DefSize;
V = new double [ s ];
if ( ! V ) { Size = 0; return; }
Size = s;
for ( s = 0; s < Size; ++s )
V [ s ] = tab ? tab [ s ] : val;
}
Vector :: Vector ( )
{
Init ( );
}
Vector :: Vector ( int s, double val )
{
Init ( s, val );
}
Tomasz Marks - Wydział MiNI PW
-11-
Projekt klasy Vector – implementacje [3]
Vector :: Vector ( int s, double tab [ ] )
{
Init ( s, 0, tab );
}
Vector :: Vector ( const Vector& arg )
{
Init ( arg.Size, 0, arg.V );
}
Vector :: ~Vector ( )
{
delete [ ] V;
}
Tomasz Marks - Wydział MiNI PW
-12-
Projekt klasy Vector – implementacje [4]
// metoda statyczna
void Vector :: setDefSize ( int newDS )
{
if ( newDS > 0 ) DefSize = newDS;
}
// metoda statyczna
int Vector :: getDefSize ( ) { return DefSize; }
int Vector :: getSize ( ) const { return Size; }
double Vector :: Norm ( ) const
{
double s = 0;
for ( int i = 0; i < Size; ++i ) s += V[ i ] * V[ i ];
return sqrt ( s );
}
Tomasz Marks - Wydział MiNI PW
-13-
Projekt klasy Vector – implementacje [5]
double Vector :: getAt ( int i ) const
{
return ( i >= 0 && i < Size ) ? V[ i ] : 0;
}
void Vector :: setAt ( int i, double val )
{
if ( i >= 0 && i < Size ) V[ i ] = val;
}
double& Vector :: operator [ ] ( int i )
{
return V[ i ];
// operacja potencjalnie niebezpieczna !!!
}
Tomasz Marks - Wydział MiNI PW
-14-
Projekt klasy Vector – implementacje [6]
double& Vector :: operator [ ] ( int i )
{
if ( i >= 0 && i < Size )
return V[ i ];
else
{
// co zrobi
ć
je
ż
eli indeks ma niedopuszczaln
ą
warto
ść
?????
}
}
Tomasz Marks - Wydział MiNI PW
-15-
Projekt klasy Vector – implementacje [7]
Vector& Vector :: operator = ( const Vector& rhs )
{
if ( this != &rhs )
{
delete [ ] V;
V = 0;
if ( rhs.Size ) V = new double [ rhs.Size ];
Size = V ? rhs.Size : 0;
for ( int i = 0; i < Size; ++i ) V[ i ] = rhs.V[ i ];
}
return *this;
}
Tomasz Marks - Wydział MiNI PW
-16-
Projekt klasy Vector – implementacje [8]
// rozwi
ą
zanie alternatywne
Vector& Vector :: operator = ( const Vector& rhs )
{
if ( this != &rhs )
{
if ( Size < rhs.Size )
// konieczna nowa alokacja
{
delete [ ] V;
// tu musi by
ć
: rhs.Size > 0
V = new double [ rhs.Size ];
Size = V ? rhs.Size : 0;
}
else
// if ( Size >= rhs.Size ) // zbyteczna nowa alokacja
Size = rhs.Size;
for ( int i = 0; i < Size; ++i ) V[ i ] = rhs.V[ i ];
}
return *this;
}
Tomasz Marks - Wydział MiNI PW
-17-
Projekt klasy Vector – implementacje [9]
Vector operator + ( const Vector& a, const Vector& b )
{
Vector sum ( ( a.Size > b.Size ) ? a.Size : b.Size );
for ( int i = 0; i < sum.Size; ++i )
{
if ( i < a.Size ) sum.V[ i ] = a.V[ i ];
if ( i < b.Size ) sum.V[ i ] += b.V[ i ];
}
return sum;
}
Tomasz Marks - Wydział MiNI PW
-18-
Projekt klasy Vector – implementacje [10]
istream& operator >> ( istream& inp, Vector& vec )
{
for ( int i = 0; i < vec.Size; ++i ) inp >> vec.V[ i ];
return inp;
}
ostream& operator << ( ostream& out, const Vector& vec )
{
for ( int i = 0; i < vec.Size; ++i )
{
if ( i % 5 == 0 ) out << endl;
out << "V[" << i << "]=" << vec.V [ i ] << " ";
}
return out;
}
Tomasz Marks - Wydział MiNI PW
-19-
Projekt klasy Vector – u
ż
ycie [1]
// vectprog.cp
# include "vector.h"
Vector A;
// wektor globalny (A.Size == 3)
double tab [ ] = { 1., 2., 3., 4., 5., 6., 7., };
………………………………
int main ( )
{
Vector B;
// wektor lokalny-automat. (B.Size==3)
int k =
Vector :: getDefSize ( );
// k==3
Vector :: setDefSize ( 5 );
Vector C;
// wektor lokalny-automat. (C.Size==5)
k = A.getSize ( );
// k==3
k =
A.getDefSize ( );
// k==5
Vector *p = 0;
k =
p->getDefSize ( );
// k==5
p = new Vector ( 7, tab );
// wektor kontrolowany (p->Size==7)
………………………………
return 0;
}
Tomasz Marks - Wydział MiNI PW
-20-
Składowe statyczne [2]
Statyczne składowe (pola i metody) nie wymagaj
ą
istnienia jakiegokolwiek
obiektu klasy, w której s
ą
zdefiniowane. Mo
ż
na si
ę
do nich odwoływa
ć
bez
zwi
ą
zku z jakim
ś
konkretnym obiektem, n.p.
Vector :: getDefSize ( )
Dla przykładowej deklaracji
Vector A, *p;
poprawne s
ą
wyra
ż
enia
A.getDefSize ( )
p->getDefSize ( )
nie oznaczaj
ą
tu działania na rzecz jakiego
ś
konkretnego obiektu;
słu
żą
jedynie do ustalenia formalnego powi
ą
zania metody statycznej
z klas
ą
obiektu u
ż
ytego bezpo
ś
rednio ( A. ) lub
po
ś
rednio za pomoc
ą
wska
ź
nika ( p-> ) na obiekty tej klasy.
Tomasz Marks - Wydział MiNI PW
-21-
Projekt klasy Vector – u
ż
ycie [2]
Vector V0;
………………………………
int main ( )
{
cout << "\n\n***START***\n";
cout << "V1";
Vector V1;
cout << "V2";
Vector V2 ( 5 );
cout << "V3";
Vector V3 ( 6, 3.5 );
cout << "V4";
Vector V4 ( 7, tab );
{
cout << "V1 lok. w bloku";
Vector V1(V4);
cout << "koniec bloku";
}
cout << "V5";
Vector V5 = V3;
cout << "przed V5 = V4 ";
V5 = V4;
cout << "po V5 = V4 ";
Vector *p = 0; cout << "*p";
p = new Vector ( 7, tab );
cout << "Vtab";
Vector Vtab[ 4 ];
………………………………
cout << "\n***STOP***\n\n";
return 0;
}
Tomasz Marks - Wydział MiNI PW
-22-
"Treningowa" wersja klasy
Vector
Tomasz Marks - Wydział MiNI PW
-23-
Projekt klasy Vector – plik definicyjny [3
a
]
class Vector
{
int Size,
Nr
;
double *V;
static int DefSize,
VCounter
;
void Init ( int size=0, double val=0, double *arr=0 );
public:
Vector ( );
Vector ( int size, double val = 0 );
Vector ( int size, double arr[ ] );
Vector ( const Vector& arg );
~Vector ( );
static void setDefSize ( int newDS );
static int getDefSize ( );
int getSize ( ) const;
double Norm ( ) const;
………………………….
Tomasz Marks - Wydział MiNI PW
-24-
Projekt klasy Vector – implementacje [1
a
]
// vector.cpp
#include <math>
#include "vector.h"
#define VECTOR_DEF_SIZE 3
int Vector::DefSize = VECTOR_DEF_SIZE;
int Vector::VCounter = 0;
// UWAGA! UWAGA! UWAGA!
// pole statyczne DefSize musi by
ć
zrefiniowane
// n.p. w pliku implementacyjnym klasy
…………………………………………………………...
……… implementacje (definicje) ………………….
……… metod klasy …………………………………..
……… i funkcji zaprzyja
ź
nionych z klas
ą
….…….
…………………………………………………………...
Tomasz Marks - Wydział MiNI PW
-25-
Projekt klasy Vector – implementacje [2
a
]
// metoda prywatna
void Vector :: Init ( int s, double val, double tab[ ] )
{
Nr = ++VCounter;
if ( s <= 0 ) s = DefSize;
V = new double [ s ];
if ( ! V ) { Size = 0; return; }
Size = s;
for ( s = 0; s < Size; ++s )
V [ s ] = tab ? tab [ s ] : val;
}
// zwykła funkcja (lokalna w pliku implementacyjnym)
static void Info ( int what, int Nr, int Size )
{
if ( what ) cout << "\nKonstruktor*" << what;
else
cout << "\nDestruktor ";
cout << " Wektor#" << Nr << " Size=" << Size << endl;
}
Tomasz Marks - Wydział MiNI PW
-26-
Projekt klasy Vector – implementacje [3
a
]
Vector :: Vector ( )
{
Init ( );
Info ( 1, Nr, Size );
}
Vector :: Vector ( int s, double val )
{
Init ( s, val );
Info ( 2, Nr, Size );
}
Vector :: Vector ( int s, double tab [ ] )
{
Init ( s, 0, tab );
Info ( 3, Nr, Size );
}
Vector :: Vector ( const Vector& arg )
{
Init ( arg.Size, 0, arg.V );
Info ( 4, Nr, Size );
}
Vector :: ~Vector ( )
{
Info ( 0, Nr, Size );
delete [ ] V;
}
Tomasz Marks - Wydział MiNI PW
-27-
Projekt klasy Vector – implementacje [7
a
]
Vector& Vector :: operator = ( const Vector& rhs )
{
// pami
ę
taj,
ż
eby nie przekopiowa
ć
numeru wektora – Nr !!!
if ( this != &rhs )
{
delete [ ] V;
V = 0;
if ( rhs.Size ) V = new double [ rhs.Size ];
Size = V ? rhs.Size : 0;
for ( int i = 0; i < Size; ++i ) V[ i ] = rhs.V[ i ];
}
return *this;
}
Tomasz Marks - Wydział MiNI PW
-28-
Co by było ... ?
• Jakie konsekwencje miałoby u
ż
ycie
predefiniowanej wersji operatora
przypisania, zamiast naszej własnej?
Tomasz Marks - Wydział MiNI PW
-29-
Predefiniowana wersja
operatora przypisania
jest równowa
ż
na nast
ę
puj
ą
cej definicji:
Vector& Vector :: operator = ( const Vector& rhs )
{
Size = rhs.Size;
Nr = rhs.Nr;
V = rhs.V;
return *this;
}
// ta wersja realizuje t.zw. "kopiowanie płytkie"
Tomasz Marks - Wydział MiNI PW
-30-
Vector V1(5), V2(7,100);
Tomasz Marks - Wydział MiNI PW
-31-
V2 = V1;
// wersja predefiniowana
Tomasz Marks - Wydział MiNI PW
-32-
V2 = V1;
// wersja predefiniowana
Tomasz Marks - Wydział MiNI PW
-33-
V2 = V1;
// "nasza" wersja
Tomasz Marks - Wydział MiNI PW
-34-
V2 = V1;
// "nasza" wersja
Tomasz Marks - Wydział MiNI PW
-35-
Koniec wykładu 5.