Wykład 4

Transkrypt

Wykład 4
Object oriented languages
dr inż. Marcin Pietroo
Overloading operators
Complex & operator = ( const Complex & c )
{
if( this != & c )
// check for a conditions
such as: a = a
{
fRe = c.fRe;
// if not the same, then
fIm = c.fIm;
// copy element by element
}
return * this;
}
Overloading operators
Complex c(10.0, 1.0);
Complex d;
d = c;
cout << d.GetRe() << ", " << d.GetIm() << endl;
Overloading operators
Complex & operator = ( const Complex & c )
{
if( this != & c ) // check for a conditions such as:
a=a
{
fRe = c.fRe; // if not the same, then
fIm = c.fIm; // copy element by element
}
return * this;
}
Overloading operators
bool operator == ( const TComplex & c ) const
{
return fRe == c.fRe && fIm == c.fIm;
}
TComplex operator + ( const TComplex & second_op ) const
{
TComplex retComplex( fRe + second_op.fRe, fIm +
second_op.fIm );
return retComplex;
}
Overloading operators
std::istream & operator >> ( std::istream & i, TComplex & complex)
{
double re, im;
i >> re;
i >> im;
complex.SetRe( re );
complex.SetIm( im );
return i;
}
std::ostream & operator << ( std::ostream & o, TComplex & complex)
{
o << complex.GetRe() << ", " << complex.GetIm();
return o;
}
Template (szablon)
C++ functionality for creating code independent from data types
and algorithms.
• function templates
• class templates
Template
template <class T> class List { ... };
List <int> list;
List <std::string> list;
List <Element> list;
Template (szablon)
#include <iostream>
#include <string>
using namespace std;
template <typename T> T const& Max (T const& a, T const& b)
{
return a < b ? b:a;
}
int main () {
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
return 0;
}
Template
template <class T> class Stack {
private:
vector<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
};
template <class T> void Stack<T>::push (T const& elem) {
elems.push_back(elem);
}
template <class T> void Stack<T>::pop () {
elems.pop_back(); }
Template
int main() {
Stack<int> intStack; // stack of ints
Stack<string> stringStack; // stack of strings
intStack.push(7);
stringStack.push("hello");
}
Java - generic
• Generic methods
• Generic classes
Generic method
public class GenericMethodTest {
public static < E > void printArray( E[] inputArray ) {
for ( E element : inputArray ) {
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] ) {
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "Array integerArray contains:" );
printArray( intArray );
System.out.println( "\nArray doubleArray contains:" );
printArray( doubleArray );
System.out.println( "\nArray characterArray contains:" );
printArray( charArray );
}
}
Generic class
public class Box<T> {
private T t;
public void add(T t) { this.t = t; }
public T get() { return t; }
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
System.out.printf("Integer Value :%d\n\n", integerBox.get());
System.out.printf("String Value :%s\n", stringBox.get());
}}
Friend method
• Nie jest ważne w którym miejscu klasy (private, protected, public)
zostanie przyjaźo zadeklarowana. Przyjaźnie danej klasy są
stosunkowo ważne z punktu widzenia projektanta, stąd też
deklaracje przyjaźni zaleca się deklarowad na samym początku
deklaracji klasy.
• Przyjaźo nie jest dziedziczona.
• Gdy istnieje wiele przeciążonych funkcji, funkcją
zaprzyjaźnioną klasy jest tylko ta funkcja, która ma zgodną listę
argumentów z zadeklarowaną funkcją zaprzyjaźnioną.
• Funkcja może byd przyjacielem wielu klas.
• Funkcją zaprzyjaźnioną może byd zarówno funkcja globalna, jak i
funkcja składowa innej klasy.
• Funkcja zaprzyjaźniona nie jest składnikiem klasy, która deklaruje
przyjaźo.
Friend class and method
class A {
friend void function( A& ); // deklaracja przyjaźni
friend void B::function( A& ); // deklaracja
przyjaźni funkcji składowej klasy B
int attr;
};
void fun( A& obiekt ) {
obiekt.attr = 1;
cout << obiekt.attr;
}
Exceptions
1) An exception is a problem that arises during the
execution of a program
2) Response to an exceptional circumstance
3) Keywords:
• throw - program throws an exception
• try - try block identifies a block of code for which
particular exceptions will be activated
• catch - program catches an exception with an
exception handler at the place in a program
where you want to handle the problem
Exceptions
try {
// protected code
}
catch( ExceptionName e1 ) {
// catch block
}
catch( ExceptionName e2 ) {
// catch block
}
catch( ExceptionName eN ) {
// catch block
}
Exception - example
double division(int a, int b)
{
if( b == 0 )
{
throw "Division by zero condition!";
}
return (a/b);
}
Exceptions - example
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
}
catch (const char* msg) {
cerr << msg << endl;
}
Exceptions - example
struct MyException : public exception {
const char * what () const throw () {
return "C++ Exception";
}
};
int main() {
try {
throw MyException();
}
catch(MyException& e) {
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
}
catch(std::exception& e) {
//Other errors
}
}
Exceptions - example
class MyException : public exception
{
public:
const char * what ()
{
return "C++ Exception";
}
};
Exceptions - example
try
{
throw MyException();
}
catch(std::exception& e)
{
std::cout << "exception" << std::endl;
}
catch(MyException& e)
{
std::cout << "MyException caught" << std::endl;
std::cout << e.what() << std::endl;
}
Exception
Description
std::exception
An exception and parent class of
all the standard C++ exceptions.
std::bad_alloc
This can be thrown by new.
std::bad_cast
This can be thrown
by dynamic_cast.
std::bad_exception
This is useful device to handle
unexpected exceptions in a C++
program
std::bad_typeid
This can be thrown by typeid.
std::logic_error
An exception that theoretically
can be detected by reading the
code.
std::domain_error
This is an exception thrown when
a mathematically invalid domain is
used
std::invalid_argument
This is thrown due to invalid
arguments.
std::length_error
This is thrown when a too big
std::string is created
Exception
Description
std::out_of_range
This can be thrown by the at method from
for example a std::vector and
std::bitset<>::operator[]().
std::runtime_error
An exception that theoretically can not be
detected by reading the code.
std::overflow_error
This is thrown if a mathematical overflow
occurs.
std::range_error
This is occured when you try to store a
value which is out of range.
std::underflow_error
This is thrown if a mathematical
underflow occurs.
Exceptions
terminate called after throwing an instance of
'std::out_of_range'
what(): vector::_M_range_check
Static
void func(void);
static int count = 10;
main() {
while(count--) {
func();
}
return 0;
}
// Function definition
void func( void ) {
static int i = 5; // local static variable
i++;
std::cout << "i is " << i ;
std::cout << " and count is " << count << std::endl;
}
Namespace
namespace namespace_name {
//code declarations
}
name::code;
Input/output
• iostream
• fstream
ifstream
ofstream
void open(const char *filename, ios::openmode mode);
fstream afile; afile.open("file.dat", ios::out | ios::in );
// position to the nth byte of fileObject (assumes ios::beg)
fileObject.seekg( n ); // position n bytes forward in fileObject
fileObject.seekg( n, ios::cur ); // position n bytes back from end of
fileObject fileObject.seekg( n, ios::end ); // position at end of fileObject
fileObject.seekg( 0, ios::end );
Casting
•
•
•
•
const cast
static cast
dynamic cast
reinterpret cast
Const cast
Konwersja uzmienniająca ma postad
• const_cast<Typ>(wyrazenie)
• Wyrażenie wyrazenie musi tu byd tego samego
typu co Typ, tylko
z modyfikatorem const lub volatile.
• Konwersja usuwa „ustalonośd” (lub „ulotnośd”)
i może służyd tylko do tego celu.
• W innych przypadkach const Typ → Typ
nielegalne
Static cast
Konwersja statyczna ma postad
• static_cast<Typ>(wyrazenie)
double x = 4;
int i = x;
warning: initialization to `int' from `double'
warning: argument to `int' from `double'
możemy uniknąd jawnie dokonując konwersji:
double x = 4;
int i = static_cast<int>(x);
Dynamic cast
Konwersja dynamiczna ma postad
• dynamic_cast<Typ>(wyrazenie)
• Konwersje dynamiczne stosuje się, gdy prawidłowośd
przekształcenia nie może byd sprawdzona na etapie
kompilacji (zależy od typu obiektu klasy
polimorficznej).
• Typ ten jest znany dopiero w czasie wykonania i wtedy
ma miejsce sprawdzenie poprawności.
• Konwersje używane są wyłącznie w odniesieniu do klas
polimorficznych i tylko dla typów wskaźnikowych
i odnośnikowych
Reinterpret cast
„Najsilniejszą” formą konwersji jest konwersja wymuszana. Ma ona
postad
• reinterpret_cast<Typ>(wyrazenie)
• Użycie takiej konwersji oznacza, że rezygnujemy ze sprawdzania jej
poprawności w czasie kompilacji i wykonania (ponosimy pełną
odpowiedzialnośd za jej skutki),
• Stosuje się ją, gdy wiemy z góry, że ani w czasie kompilacji, ani
w czasie wykonania nie będzie możliwe określenie jej sensowności,
• Można, na przykład, dokonad
konwersji char* → int* lub klasaA* → klasaB*, gdzie
klasy klasaA i klasaB są zupełnie niezależne, takie konwersje nie są
bezpieczne,
Dynamic cast
Operator dynamicznego
rzutowania (konwersji) stosuje się, gdy
prawidłowośd przekształcenia nie może byd
sprawdzona na etapie kompilacji (zależy od typu
obiektu klasy polimorficznej), który znany jest
dopiero w czasie wykonania.
Jego użycie ma sens w sytuacjach, gdy mamy do
czynienia z obiektami różnych klas powiązanych
ze sobą hierarchią dziedziczenia.
Dynamic cast
• dynamic_cast<Typ>(wyrazenie)
Typ Typ jest typem wskaźnikowym do polimorficznej klasy pochodnej,
czyli Typ = B*, a wartością wyrażenia wyrazenie jest wskazanie na
obiekt klasy bazowej A, czyli wartośd o typie A*. Operacja rzutowania
polega wtedy na sprawdzeniu, czy obiekt wskazywany
przez wyrazenie jest w rzeczywistości obiektem klasy pochodnej B; po
tym teście wartością całego tego wyrażenia staje się
– wartośd wskaźnikowa typu B* wskazująca na obiekt wskazywany
przez wyrazenie, jeśli test wypadł pomyślnie;
– zero (wskaźnik pusty, NULL), jeśli test się nie powiódł, czyli obiekt
wskazywany przez wyrazenie nie jest obiektem klasy B. Można to
w programie sprawdzid odpowiednim if'em i podjąd stosowne
działania bez przerywania programu.
Dynamic cast
Typ Typ jest typem referencyjnym do polimorficznej klasy pochodnej,
czyli Typ = B&, a wartością wyrażenia wyrazenie jest l-nazwa obiektu
klasy A. Operacja rzutowania polega wtedy na sprawdzeniu, czy
obiekt wyrazenie jest w rzeczywistości obiektem klasy pochodnej B, po
tym teście:
– jeśli wypadł pomyślnie, wartością całego wyrażenia staje się
odniesienie typu B& do obiektu wyrazenie;
– jeśli wypadł niepomyślnie, bo obiekt wyrazenie nie jest typu B, to
zgłaszany jest wyjątek typu bad_cast (z nagłówka typeinfo), który
można przechwycid i podjąd stosowne działania bez przerywania
programu. Tym razem nie można przekazad informacji
o niepowodzeniu zerową wartością wyrażenia, bo nie ma czegoś
takiego jak puste odniesienie (tak jak jest pusty, czyli zerowy,
wskaźnik). Dlatego do obsługi tego przypadku wybrano metodę
zgłoszenia wyjątku.
Dynamic cast
class Program {
protected:
string name;
public:
Program(string n) : name(n) { }
virtual void print() = 0;
virtual ~Program() { }
};
class Freeware : public Program {
public:
Freeware(string n)
Program(n) { }
void print() {
cout << "Free : " << name << endl;
}
};
Dynamic cast
class Shareware : public Program {
int price;
public:
Shareware(string n, int c) : Program(n), price(c) { }
void print() {
cout << "Share: " << name << ", price " << price << endl;
}
int getPrice() {
return price;
}
};
Dynamic cast
int total(Program* prgs[], int size) {
Shareware* sh;
int tot = 0;
for (int i = 0; i < size; ++i) {
prgs[i]->print();
if ( sh = dynamic_cast<Shareware*>(prgs[i]))
tot += sh->getPrice();
}
return tot;
}
Dynamic cast
int main(void) {
Freeware mongodb(„mongodb");
Shareware wz("WinZip",30);
Freeware mysql("MySQL");
Shareware rar("RAR",25);
Program* prgs[] = { &mongodb, &wz, &mysql, &rar };
int tot = total(prgs, sizeof(prgs)/sizeof(prgs[0]));
cout << "\nTotal: $" << tot << endl;
}
Dynamic cast (reference)
int total(Program* prgs[], int size) {
int tot = 0;
for (int i = 0; i < size; ++i) {
prgs[i]->print();
try {
Shareware& sh = dynamic_cast<Shareware&>(*prgs[i]);
tot += sh.getPrice();
}
catch(bad_cast) { }
}
return tot;
}
Reinterpret_cast
char* buff1 = new char[size];
reinterpret_cast<char*>(&person_object);
Person* p1 = reinterpret_cast<Person*>(buff1);
References and pointers
int * const z1 = &i;
z1 = &j;
*z1 = *z1 + 10;
References and pointers
int x = 10;
int &x_ref = x;
x = 12
x_ref = 12;
int *x_ptr = &x;
*x_ptr = 12;
References and pointers
int &x_ref;
int &x_ref = 10;
const int &w = 10;
int x = 10;
int &x_ref = x;
int && x_ref_ref = x_ref;
References and pointers
• access to element without copy
• reference must be initiated during declaration
• reference to variable is actual during whole
program
• reference can’t be multidimensional
References and pointers
Difference between:
- const type * identifier
- type const* identifier
Task
Implementation of vector and list classes

Podobne dokumenty