Documente Academic
Documente Profesional
Documente Cultură
Dorin Mancu
dmancu@memiq.ro
Obiective
int main() {
B b;
A& r = b;
A* p = &b;
cout << typeid(r).name() << endl;
cout << typeid(*p).name() << endl;
}
Operatorul dynamic_cast<>
dynamic_cast<B&> (a) – se încearcă conversia
obiectului la o referință de tip B
Se folosește de obicei pentru downcasting (tip
părinte tip fiu)
Două variante:
pointer; NULL dacă nu e posibil
referințe; excepție std::bad_cast dacă nu e
posibil
Durata depinde de complexitatea lanțului de
moștenire
Notă: upcasting la moștenire multiplă
Exemplu de folosire dynamic_cast<>:
struct A
{
int i;
virtual ~A () {} //enforce polymorphism; needed for dynamic_cast
};
struct B
{
bool b;
};
struct D: public A, public B
{
int k;
D() { b = true; i = k = 0; }
};
A *pa = new D;
B *pb = dynamic_cast<B*> pa; //cross cast; access the second base
//of a multiple-derived object
static_cast<>
nu este așa sigur ca dynamic_cast, se bazează
doar pe informațiile de la compilare
Exemplu:
A* pa = new A();
B* pb;
pb = static_cast<B*> (pa);
class A {
public:
virtual ~A(){}
};
class B: public A { };
int main()
{
A* pa = new B; // new A;
B* pb1 = static_cast<B*>(pa);
B* pb2 = dynamic_cast<B*>(pa);
}
Cast C
class A { };
class B: public A { };
int main()
{
B* pb = new B;
A* pa1 = (A*) pb;
A* pa2 = static_cast<A*>(pb);
return 0;
}
Funcții speciale de conversie de la o clasă la un
tip – suport pentru cast
Exemplu pentru Contor
operator int*() { return &val; }
Contor c;
int *pi = (int*) c;
reinterpret_cast<>
Programare generică
Specificarea unei familii de clase sau
funcții
Generarea de clase / cod la compilare
template <class T> class Vector; //declaration
template <class T> inline T& Vector<T>::operator [] (unsigned int i) { return buff[i]; }
int main() {
Vector <int> x;
Vector <int, unsigned char> y(5);
return 0;
}
Membrii statici
template<class T> class C {
public:
static T stat;
};
template<class T> T C<T>::stat = 5; //definiție
void f() {
int n = C<int>::stat;
}
Friendship
template <class T> class Vector {
public:
//...
friend void f ();
friend class A;
friend class B<int>;
template <class U> friend class C;
};
Specializare parțială – oferă o definiție alternativă la
template-ul primar
template <class T> class Vector <T*> //partial specialization of Vector <T>
{
private:
size_t size;
void * p;
public:
Vector();
~Vector();
//...member functions
size_t size() const;
};
template <class T> bool operator== ( const Vector<T>& v1, const Vector<T>& v2 ) {
if (v1.size() != v2.size()) return false;
for (size_t i = 0; i<v1.size(); i++) {
if (v1[i] != v2[i]) return false;
}
return true;
}
template <> bool operator== <const char*> (const Vector<const char *>& v1,
const Vector<const char *>& v2) {
if (v1.size() != v2.size()) return false;
for (size_t i = 0; i<v1.size(); i++) {
if (strcmp(v1[i], v2[i]) != 0) return false;
}
return true;
}
Template-uri funcție
template <class T> T max( T t1, T t2) {
return (t1 > t2) ? t1 : t2;
}
Dacă se oferă variantă pentru int se va folosi prioritar:
int max (int i, int j) {
return (i > j) ? i : j;
}
// iterator
found = find_if(l.begin(), l.end(), selection);
Containere specializate
vector<bool> - un bool / bit
Containere asociative (map)
elemente pair<class Key, class Value>
enum directions {up, down};
Concurență
procese
în cadrul proceselor – fire de execuție
Motive
partiționare/separare/specializare funcțională
eficiență
Concurența și C++
acces la resursele SO gazdă; cod specific
platformei (de obicei prin C):
Unix - IEEE POSIX 1003.1c
Windows
biblioteci, framework specializat
(independență de platformă) – BOOST, ACE
standardul C++11 introduce Standard C++
Thread Library
Fire de execuție – generalități
Creare fir de execuție – funcție executată
Terminare – funcția se termină, colaborare
pentru oprirea firelor de execuție
Prioritate
Planificarea firelor de execuție (scheduler)
Stările firelor de execuție
Acces la resurse comune – acces exclusiv
Sincronizare fire de execuție
Comunicare între fire de execuție
Fire de execuție POSIX
Paralelism în cadrul unui proces
Thread-urile trăiesc în același spațiu de nume/proces:
au propria stivă
au în comun: variabile globale, descriptori fișiere, resurse
proces
Standard IEEE POSIX 1003.1c (Portable Operating
System Interface)
există implementări sub orice sistem de operare
definește un API C
Programare multithreading:
Avantaj: specializare/partiționare aplicație
Dezavantaj: complexitate cod
Configurare în Linux:
include pthread.h
#define _REENTRANT - înaintea include-urilor
(compilator –D_REENTRANT)
efect: funcțiile standard devin reentrante,
errno / thread
linker –lpthread
Configurare în Windows
http://www.sourceware.org/pthreads-win32/
adăugare directori include și lib
adăugare pthreadVC2.lib
pthreadVC2.dll – lângă executabil
Manipularea firelor de execuție
#include <pthread.h>
int pthread_create(pthread_t *thread,
pthread_attr_t *attr,
void* (*start_routine)(void *),
void *arg);
void pthread_exit(void *retval);
int pthread_join(pthread_t th, void **thread_return);
Alte funcții:
int pthread_cancel(pthread_t th);
int pthread_detach(pthread_t th); // nu este join-able
pthread_t pthread_self();
int pthread_equal(pthread_t t1, pthread_t t2);
Controlul atributelor: mărime stivă, detașat, etc
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
Exemplu de folosire:
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr,
PTHREAD_CREATE_DETACHED);
pthread_create(&a_thread, &thread_attr, thread_function,
(void *) message);
pthread_attr_destroy(&thread_attr);
Vezi exemplu: threads 3 (control stack size)
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
Inițializare statică:
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
Vezi exemplul threads 5
Alte funcții:
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_timedlock(pthread_mutex_t *mutex,
const struct timespec *deltatime);
Performanță mutex – cere timp
Deadlock – interblocarea thread-urilor (ordinea de
achiziție!)
Tipuri de mutex:
PTHREAD_MUTEX_NORMAL - fast mutex
(implicit) – apare deadlock dacă un thread face
lock pe același mutex de două ori!
PTHREAD_MUTEX_RECURSIVE
PTHREAD_MUTEX_ERRORCHECK – la al
doilea lock pe același mutex se returnează
EDEADLK în loc de deadlock
Exemplu pentru crearea unui mutex cu verificare de eroare
pthread_mutex_t mtx;
pthread_mutexattr_t mtxAttr;
int s, type;
s = pthread_mutexattr_init(&mtxAttr);
if (s != 0) err();
s = pthread_mutexattr_settype(&mtxAttr,
PTHREAD_MUTEX_ERRORCHECK);
if (s != 0) err();
s = pthread_mutex_init(&mtx, &mtxAttr);
if (s != 0) err();
....
s = pthread_mutexattr_destroy(&mtxAttr);
if (s != 0) err;
Variabile condiție
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond,
const pthread_condattr_t *attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_condattr_destroy(pthread_condattr_t *attr);
int pthread_condattr_init(pthread_condattr_t *attr);
int pthread_cond_wait(pthread_cond_t *cond,
pthread_mutex_t *mutex);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_timedwait(pthread_cond_t *cond,
pthread_mutex_t *mutex, const struct timespec *abstime);