Oop Curs3 PDF
Oop Curs3 PDF
pe obiecte
Seria 14
Saptamana 3, 5 martie 2013
Andrei Paun
Clasele in C++
cu class
obiectele instantiaza clase
similare cu struct-uri si union-uri
au functii
specificatorii de acces: public, private, protected
default: private
protected: pentru mostenire, vorbim mai tarziu
class class-name {
private data and functions
access-specifier:
data and functions
access-specifier:
data and functions
// ...
access-specifier:
data and functions
} object-list;
class employee {
char name[80]; // private by default
public:
void putname(char *n); // these are public
void getname(char *n);
private:
double wage; // now, private again
public:
void putwage(double w); // back to public
double getwage();
};
class employee {
char name[80];
double wage;
public:
void putname(char *n);
void getname(char *n);
void putwage(double w);
double getwage();
};
Exemplu
#include <iostream>
using namespace std;
class myclass {
public:
int i, j, k; // accessible to entire program
};
int main()
{
myclass a, b;
a.i = 100; // access to i, j, and k is OK
a.j = 4;
a.k = a.i * a.j;
b.k = 12; // remember, a.k and b.k are different
cout << a.k << " " << b.k;
return 0;
}
Struct si class
singura diferenta: struct are default membri
ca public iar class ca private
struct defineste o clasa (tip de date)
putem avea in struct si functii
int main() {
mystr s;
s.buildstr(""); // init
s.buildstr("Hello ");
s.buildstr("there!");
s.showstr();
return 0;
}
class mystr {
char str[255];
public:
void buildstr(char *s); // public
void showstr();
};
union si class
la fel ca struct
toate elementele de tip data folosesc aceeasi
locatie de memorie
membrii sunt publici (by default)
#include <iostream>
using namespace std;
union swap_byte {
void swap();
void set_byte(unsigned short i);
void show_word();
unsigned short u;
unsigned char c[2];
};
void swap_byte::swap()
{
unsigned char t;
t = c[0];
c[0] = c[1];
c[1] = t;
}
void swap_byte::show_word()
{
cout << u;
}
void swap_byte::set_byte(unsigned short i)
{
u = i;
}
int main()
{
swap_byte b;
b.set_byte(49034);
b.swap();
b.show_word();
return 0;
}
35519
union ca si class
union anonime
nu au nume pentru tip
nu se pot declara obiecte de tipul respectiv
folosite pentru a spune compilatorului cum
se tin variabilele respective in memorie
folosesc aceeasi locatie de memorie
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
// define anonymous union
union {
long l;
double d;
char s[4];
};
union anonime
nu poate avea functii
nu poate avea private sau protected (fara
functii nu avem acces la altceva)
union-uri anonime globale trebuie precizate
ca static
functii prieten
cuvantul: friend
pentru accesarea campurilor protected,
private din alta clasa
folositoare la overload-area operatorilor,
pentru unele functii de I/O, si portiuni
interconectate (exemplu urmeaza)
in rest nu se prea folosesc
#include <iostream>
using namespace std;
class myclass {
int a, b;
public:
friend int sum(myclass x);
void set_ab(int i, int j);
};
void myclass::set_ab(int i, int j) { a = i; b = j; }
#include <iostream>
using namespace std;
const int IDLE = 0;
const int INUSE = 1;
class C2; // forward declaration
class C1 {
int status; // IDLE if off, INUSE if on screen
// ...
public:
void set_status(int state);
friend int idle(C1 a, C2 b);
};
class C2 {
int status; // IDLE if off, INUSE if on screen
// ...
public:
void set_status(int state);
friend int idle(C1 a, C2 b);
};
#include <iostream>
using namespace std;
const int IDLE = 0;
const int INUSE = 1;
class C2; // forward declaration
class C1 {
int status; // IDLE if off, INUSE if on screen
// ...
public:
void set_status(int state);
int idle(C2 b); // now a member of C1
};
class C2 {
int status; // IDLE if off, INUSE if on screen
// ...
public:
void set_status(int state);
friend int C1::idle(C2 b);
};
void C1::set_status(int state)
{
status = state;
}
clase prieten
daca avem o clasa prieten, toate functiile
membre ale clasei prieten au acces la
membrii privati ai clasei
class TwoValues {
int a;
int b;
public:
TwoValues(int i, int j) { a = i; b = j; }
friend class Min;
};
class Min {
public:
int min(TwoValues x);
};
int Min::min(TwoValues x)
{ return x.a < x.b ? x.a : x.b; }
int main()
{
TwoValues ob(10, 20);
Min m;
cout << m.min(ob);
return 0;
}
functii inline
foarte comune in clase
doua tipuri: explicit (inline) si implicit
Explicit
#include <iostream>
using namespace std;
#include <iostream>
using namespace std;
int main()
{
cout << (10>20 ? 10 : 20);
cout << " " << (99>88 ? 99 : 88);
return 0;
}
int main()
{
cout << max(10, 20);
cout << " " << max(99, 88);
return 0;
}
functii inline
executie rapida
este o sugestie/cerere pentru compilator
pentru functii foarte mici
pot fi si membri ai unei clase
#include <iostream>
using namespace std;
class myclass {
int a, b;
public:
void init(int i, int j);
void show();
};
// Create an inline function.
inline void myclass::init(int i, int j)
{ a = i; b = j; }
// Create another inline function.
inline void myclass::show()
{ cout << a << " " << b << "\n"; }
int main()
{
myclass x;
x.init(10, 20);
x.show();
return 0;
}
#include <iostream>
using namespace std;
class myclass {
class myclass {
int a, b;
int a, b;
public:
public:
// automatic inline
// automatic inline
void init(int i, int j)
void init(int i, int j) { a=i; b=j; }
{
void show() { cout << a << " " << b << "\n"; } a = i;
};
b = j;
int main()
{
myclass x;
x.init(10, 20);
x.show();
return 0;
}
}
void show()
{
cout << a << " " << b << "\n";
}
};
Constructori parametrizati
trimitem argumente la constructori
putem defini mai multe variante cu mai
multe numere si tipuri de parametrii
overload de constructori
#include <iostream>
using namespace std;
class myclass {
int a, b;
public:
myclass(int i, int j) {a=i; b=j;}
void show() {cout << a << " " << b;}
};
int main()
{
myclass ob(3, 5);
ob.show();
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
const int IN = 1;
const int CHECKED_OUT = 0;
class book {
char author[40];
char title[40];
int status;
public:
book(char *n, char *t, int s);
int get_status() {return status;}
void set_status(int s) {status = s;}
void show();
};
void book::show()
{
cout << title << " by " << author;
cout << " is ";
if(status==IN) cout << "in.\n";
else cout << "out.\n";
}
int main()
{
book b1("Twain", "Tom Sawyer", IN);
book b2("Melville", "Moby Dick", CHECKED_OUT);
b1.show();
b2.show();
return 0;
}
constructori cu un paramentru
se creeaza o conversie implicita de date
#include <iostream>
using namespace std;
class X {
int a;
public:
X(int j) { a = j; }
int geta() { return a; }
};
int main()
{
X ob = 99; // passes 99 to j
cout << ob.geta(); // outputs 99
return 0;
}
#include <iostream>
using namespace std;
class shared {
static int a;
int b;
public:
void set(int i, int j) {a=i; b=j;}
void show();} ;
int shared::a; // define a
This is static a: 1
This is non-static b: 1
This is static a: 2
This is non-static b: 2
This is static a: 2
This is non-static b: 1
void shared::show(){
cout << "This is static a: " << a;
cout << "\nThis is non-static b: " << b;
cout << "\n";}
int main(){
shared x, y;
x.set(1, 1); // set a to 1
x.show();
y.set(2, 2); // change a to 2
y.show();
x.show(); /* Here, a has been changed for both x and y
because a is shared by both objects. */
return 0;}
#include <iostream>
using namespace std;
class shared {
public:
static int a;
};
int shared::a; // define a
int main()
{
// initialize a before creating any objects
shared::a = 99;
cout << "This is initial value of a: " << shared::a;
cout << "\n";
shared x;
cout << "This is x.a: " << x.a;
return 0;
}
#include <iostream>
using namespace std;
class cl {
static int resource;
public:
int get_resource();
void free_resource() {resource = 0;}
};
int cl::resource; // define resource
int main()
{
cl ob1, ob2;
if(ob1.get_resource()) cout << "ob1 has resource\n";
if(!ob2.get_resource()) cout << "ob2 denied resource\n";
ob1.free_resource(); // let someone else use it
if(ob2.get_resource())
cout << "ob2 can now use resource\n";
return 0;
}
int cl::get_resource()
{
if(resource) return 0; // resource already in use
else {
resource = 1;
return 1; // resource allocated to this object
}
}
Alte exemplu
Numararea obiectelor dintr-o clasa
#include <iostream>
using namespace std;
class Counter {
public:
static int count;
Counter() { count++; }
~Counter() { count--; }
};
void f()
{
Counter temp;
cout << "Objects in existence: ";
cout << Counter::count << "\n";
// temp is destroyed when f() returns
}
int Counter::count;
void f();
int main(void)
{
Counter o1;
cout << "Objects in existence: ";
cout << Counter::count << "\n";
Counter o2;
cout << "Objects in existence: ";
cout << Counter::count << "\n";
f();
cout << "Objects in existence: ";
cout << Counter::count << "\n";
return 0;
}
Objects in existence: 1
Objects in existence: 2
Objects in existence: 3
Objects in existence: 2
#include <iostream>
using namespace std;
class cl {
static int resource;
public:
static int get_resource();
void free_resource() { resource = 0; }
};
int cl::resource; // define resource
int main()
{
cl ob1, ob2;
/* get_resource() is static so may be called
independent of any object. */
if(cl::get_resource()) cout << "ob1 has resource\n";
if(!cl::get_resource()) cout << "ob2 denied resource\n";
ob1.free_resource();
if(ob2.get_resource()) // can still call using object syntax
cout << "ob2 can now use resource\n";
return 0;
int cl::get_resource()
}
{
if(resource) return 0; // resource already in use
else {
resource = 1;
return 1; // resource allocated to this object
}
}
#include <iostream>
using namespace std;
class static_type {
static int i;
public:
static void init(int x) {i = x;}
void show() {cout << i;}
};
int static_type::i; // define i
int main()
{
// init static data before object creation
static_type::init(100);
static_type x;
x.show(); // displays 100
return 0;
}
folosirea uzuala a
functiilor statice
#include <iostream>
using namespace std;
class myclass {
int who;
public:
myclass(int id);
~myclass();
} glob_ob1(1), glob_ob2(2);
myclass::myclass(int id)
{
cout << "Initializing " << id << "\n";
who = id;}
Initializing 1
Initializing 2
Initializing 3
This will not be first line displayed.
Initializing 4
Destructing 4
Destructing 3
Destructing 2
Destructing 1
myclass::~myclass()
{ cout << "Destructing " << who << "\n";}
int main()
{
myclass local_ob1(3);
cout << "This will not be first line displayed.\n";
myclass local_ob2(4);
return 0;
}
int i; // global i
void f()
{
int i; // local i
::i = 10; // now refers to global i
.
.
.
}
Clase locale
putem defini clase in clase sau functii
class este o declaratie, deci defineste un
scop
operatorul de rezolutie de scop ajuta in
aceste cazuri
rar utilizate clase in clase
#include <iostream>
using namespace std;
void f();
int main()
{
f();
// myclass not known here
return 0;
}
void f()
{
class myclass {
int i;
public:
void put_i(int n) { i=n; }
int get_i() { return i; }
} ob;
ob.put_i(10);
cout << ob.get_i();
}
class myclass {
int i;
public:
myclass(int n);
~myclass();
void set_i(int n) { i=n; }
int get_i() { return i; }
};
myclass::myclass(int n)
{
i = n;
cout << "Constructing " << i << "\n";
}
myclass::~myclass()
{
cout << "Destroying " << i << "\n";
}
int main()
{
myclass o(1);
f(o);
cout << "This is i in main: ";
cout << o.get_i() << "\n";
return 0;
}
void f(myclass ob)
{
ob.set_i(2);
cout << "This is local i: " << ob.get_i();
cout << "\n";
}
Constructing 1
This is local i: 2
Destroying 2
This is i in main: 1
Destroying 1
Discutie
apelam constructorul cand creem obiectul o
apelam de DOUA ori destructorul
la apel de functie: apel prin valoare, o copie
a obiectului e creata
apelam constructorul?
la finalizare apelam destructorul?
Constructor de copiere
C++ il defineste pentru a face o copie
identica pe date
constructorul e folosit pentru initializare
constr. de copiere e folosit pentru obiect
deja initializat, doar copiaza
vrem sa folosim starea curenta a obiectului,
nu starea initiala a unui obiect din clasa
respectiva
class myclass {
int i;
public:
void set_i(int n) { i=n; }
int get_i() { return i; }
};
myclass f(); // return object of type myclass
int main()
{
myclass o;
o = f();
cout << o.get_i() << "\n";
return 0;
}
myclass f()
{
myclass x;
x.set_i(1);
return x;
}
// Assigning objects.
#include <iostream>
using namespace std;
class myclass {
int i;
public:
void set_i(int n) { i=n; }
int get_i() { return i; }
};
int main()
{
myclass ob1, ob2;
ob1.set_i(99);
ob2 = ob1; // assign data from ob1 to ob2
cout << "This is ob2's i: " << ob2.get_i();
return 0;
}
#include<iostream.h>
class B
{ int i;
public: B() { i=1; }
virtual int get_i() { return i; }
};
class D: public B
{ int j;
public: D() { j=2; }
int get_i() {return B::get_i()+j; }
};
int main()
{ const int i = cin.get();
if (i%3) { D o;}
else {B o;}
cout<<o.get_i();
return 0;
}
#include <iostream.h>
class A
{ static int x;
public: A(int i=0) {x=i; }
int get_x() { return x; }
int& set_x(int i) { x=i;}
A operator=(A a1) { set_x(a1.get_x()); return a1;}
};
int main()
{ A a(212), b;
cout<<(b=a).get_x();
return 0;
}
#include<iostream.h>
class B
{ int i;
public: B() { i=1; }
virtual int get_i() { return i; } };
class D: virtual public B
{ int j;
public: D() { j=2; }
int get_i() {return B::get_i()+j; } };
class D2: virtual public B
{ int j2;
public: D2() { j2=3; }
int get_i() {return B::get_i()+j2; } };
class MM: public D, public D2
{ int x;
public: MM() { x=D::get_i()+D2::get_i(); }
int get_i() {return x; } };
int main()
{ B *o= new MM();
cout<<o->get_i()<<"\n";
MM *p= dynamic_cast<MM*>(o);
if (p) cout<<p->get_i()<<"\n";
D *p2= dynamic_cast<D*>(o);
if (p2) cout<<p2->get_i()<<"\n";
return 0;
}
#include<iostream.h>
class B
{ protected: int x;
public: B(int i=28) { x=i; }
virtual B f(B ob) { return x+ob.x+1; }
void afisare(){ cout<<x; } };
class D: public B
{ public: D(int i=-32):B(i) {}
B f(B ob) { return x+ob.x-1; } };
int main()
{ B *p1=new D, *p2=new B, *p3=new B(p1->f(*p2));
p3->afisare();
return 0;
}