NazWektor

Transkrypt

NazWektor
Wyliczanie wyrażenia – obiekty tymczasowe
Bogdan Kreczmer
ZPCiR IIAiR PWr
pokój 307 budynek C3
[email protected]
c 2013 Bogdan Kreczmer?
Copyright ? Niniejszy dokument zawiera materiały do wykładu na temat programowania obiektowego. Jest on udostepniony
˛
pod warun-
kiem wykorzystania wyłacznie
˛
do własnych prywatnych potrzeb i może on być kopiowany wyłacznie
˛
w całości, razem z niniejsza˛
strona˛ tytułowa.
˛
Czas życia obiektów tymczasowych
int main( )
{
NazWektor W a(”a”, 1, 2), W b(”b”, 1, 1), W c(”c”, 1, 0), W d(”d”, 2, 2), W r(”r”);
cout << ”—- Poczatek operacji dodawania —————–” << endl;
W r = (W a + W b) + (W c + W d);
cout << ”—- Koniec operacji dodawania ——————-” << endl;
cout << ”—- Rezultat: ” << W r << endl;
}
Wykonywaniu poszczególnych operacji towarzyszy tworzenie sie˛ obiektów tymczasowych. Chcac
˛
prześledzić ten proces, należy przeciażyć
˛
odpowiednie konstruktory. Przeciażenia
˛
te musza˛ zapewniać możliwość nazwania obiektów, tak aby można było prześledzić okres życia poszczególnych
obiektów.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
1
Czas życia obiektów tymczasowych
class NazWektor { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
static char ZnakCyfry;
public :
string Nazwa;
float
x, y;
NazWektor(const char ∗Nazwa, float x = 0, float y = 0 );
NazWektor( const NazWektor & W );
∼
NazWektor( );
NazWektor
operator + ( const NazWektor & W ) const;
NazWektor & operator = ( const NazWektor & W );
}; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
char NazWektor:: ZnakCyfry = ’0’;
int main( )
{
NazWektor W( ”a” , 1, 2 );
}
ostream & operator << ( ostream & ostrm, const NazWektor & W )
{
return ostrm << W. Nazwa << ”(” << W. x << ”, ” << W. y << ”)”;
}
cout << W << endl;
Wynik działania:
a(1, 2)
Wprowadzenie dodatkowego pola statycznego pozwala numerować tworzace
˛
sie˛ tymczasowe
obiekty. Zaś pole Nazwa pozwala nazywać każdy z obiektów.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
2
Definicje konstruktora i destruktora
class NazWektor { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
static char ZnakCyfry;
public :
string Nazwa;
float
x, y;
NazWektor(const char ∗Nazwa, float x = 0, float y = 0 );
...
∼
NazWektor( );
...
}; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
NazWektor::NazWektor( const char ∗Nazwa, float x, float y ): Nazwa(Nazwa)
{
x = x; y = y; cout << ”++ Konstruktor: ” << ∗this << endl;
int main( )
{
}
NazWektor W( ”a” , 1, 2 );
}
NazWektor::∼ NazWektor( )
{
cout << ”++ Destruktor: ” << ∗this << endl;
}
Wynik działania:
++ Konstruktor: a(1, 2)
−− Destruktor: a(1, 2)
Wywołanie konstruktora lub destruktora jest sygnalizowane odpowiednim komunikatem na wyjściu
standardowym. Podaje on nazwe˛ i wartości pól obiektu.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
3
Konstruktor kopiujacy
˛
class NazWektor { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
static char ZnakCyfry;
public :
string Nazwa;
x, y;
float
...
NazWektor( const NazWektor & W );
...
}; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
NazWektor::NazWektor( const NazWektor & W ): Nazwa(”Tmp”)
{
Nazwa += ++ ZnakCyfry;
x = y = 0;
cout << ”.. Kopiuje: ” << ∗this << ” <- ” << W << endl;
x = W. x; y = W. y;
}
int main( )
{
NazWektor W( ”a” , 1, 2 );
NazWektor V(W);
}
Wynik działania:
++ Konstruktor: a(1, 2)
++ Kopiuje: Tmp1(0,0) <- a(1, 2)
−− Destruktor: Tmp1(1, 2)
−− Destruktor: a(1, 2)
Konstruktor kopiujacy
˛ w tym rozwiazaniu
˛
nie powoduje przepisanie nazwy obiektu. Jest to niezbedne,
˛
aby móc zidentyfikować nowy obiekt. Jego nazwa tworzona jest automatycznie.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
4
Operator dodawania
class NazWektor { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
static char ZnakCyfry;
public :
string Nazwa;
x, y;
float
...
NazWektor operator + ( const NazWektor& W ) const;
...
}; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
NazWektor NazWektor::operator + ( const NazWektor& W ) const
{
cout << ”.. Dodanie: ” << ∗this << ” + ” << W << endl;
string Nazwa( ”Tmp” );
Nazwa += ++ ZnakCyfry;
return NazWektor( Nazwa.c str(), x+W. x, y+W. y );
}
int main( )
{
NazWektor W( ”a” , 1, 2 );
W = W + W;
}
Wynik działania:
++ Konstruktor:
.. Dodanie: a(1,
++ Konstruktor:
−− Destruktor:
−− Destruktor:
a(1, 2)
2) + a(1,2)
Tmp1(2, 4)
Tmp1(2, 4)
a(1, 2)
W trakcie realizacji operacji dodawania tworzony jest obiekt tymczasowy, który przekazuje ”na zewnatrz”
˛
wynik działania.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
5
Operator przypisania
class NazWektor { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
static char ZnakCyfry;
public :
string Nazwa;
x, y;
float
...
NazWektor & operator = ( const NazWektor & W );
...
}; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
NazWektor & NazWektor::operator = ( const NazWektor & W )
{
cout << ”.. Podstawienie: ”
<< ∗this << ” = ” << W << endl;
x = W. x; y = W. y;
return ∗this ;
}
int main( )
{
NazWektor W( ”a” , 1, 2 );
W = W;
}
Wynik działania:
++ Konstruktor: a(1, 2)
.. Podstawienie: a(1, 2) = a(1,2)
−− Destruktor: a(1, 2)
Realizacja operacji podstawienia nie wymaga tworzenia żadnych obiektów tymczasowych. Zarówno
argument, jak też wynik działania, zwracane sa˛ przez referencje.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
6
W r = (W a + W b) + (W c + W d)
class NazWektor { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
static char ZnakCyfry;
public :
string Nazwa;
float
x, y;
NazWektor(const char ∗Nazwa, float x = 0, float y = 0);
NazWektor( const NazWektor & W );
∼ NazWektor( );
NazWektor
operator + ( const NazWektor & W )
const;
NazWektor & operator = ( const NazWektor & W );
}; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
...
int main()
{
NazWektor
Wa(”a”,1,2), Wb(”b”,1,1), Wc(”c”,1,0),
Wd(”d”,2,2);
NazWektor Wr(”r”);
cout << ”— Poczatek operacji dodawania ——-” << endl;
Wr = (Wa + Wb) + (Wc + Wd);
cout << ”— Koniec operacji dodawania ———-” << endl;
cout << ”— Rezultat: ” << Wr << endl;
}
c 2013 Bogdan Kreczmer
Copyright Wynik działania:
++ Konstruktor:
++ Konstruktor:
++ Konstruktor:
++ Konstruktor:
++ Konstruktor:
a(1, 2)
b(1, 1)
c(1, 0)
d(2, 2)
r(0, 0)
— Poczatek operacji dodawania ———.. Dodanie: c(1, 0) + d(2, 2)
++ Konstruktor: Tmp1(3, 2)
.. Dodanie: a(1, 2) + b(1, 1)
++ Konstruktor: Tmp2(2, 3)
.. Dodanie: Tmp2(2, 3) + Tmp1(3, 2)
++ Konstruktor: Tmp3(5, 5)
.. Podstawienie: r(0, 0) = Tmp3(5, 5)
++ Destruktor: Tmp3(5, 5)
++ Destruktor: Tmp2(2, 3)
++ Destruktor: Tmp1(3, 2)
— Koniec operacji dodawania ————
— Rezultat: r(5, 5)
++ Destruktor:
++ Destruktor:
++ Destruktor:
++ Destruktor:
++ Destruktor:
r(5, 5)
d(2, 2)
c(1, 0)
b(1, 1)
a(1, 2)
Wyliczanie wyrażenia – obiekty tymczasowe
7
W r = (W a + W b) + (W c + W d)
...
— Poczatek operacji dodawania ———.. Dodanie: c(1, 0) + d(2, 2)
W r = (W a + W b) + (W c + W d);
⇓
++ Konstruktor: Tmp1(3, 2)
.. Dodanie: a(1, 2) + b(1, 1)
W r = (W a + W b) +
W r = (W a + W b) +
Tmp1
Tmp1
;
;
Tmp1
Tmp1
;
;
⇓
++ Konstruktor: Tmp2(2, 3)
.. Dodanie: Tmp2(2, 3) + Tmp1(3, 2)
W r=
W r=
Tmp2
Tmp2
+
+
⇓
++ Konstruktor: Tmp3(5, 5)
.. Podstawienie: r(0, 0) = Tmp3(5, 5)
++ Destruktor: Tmp3(5, 5)
++ Destruktor: Tmp2(2, 3)
++ Destruktor: Tmp1(3, 2)
W r=
W r=
W r
Tmp3
Tmp3
;
;
−→;
— Koniec operacji dodawania ————
— Rezultat: r(5, 5)
...
W trakcie realizacji całej operacji tworza˛ sie˛ obiekty pośrednie, które przekazuja˛ wyniki cz˛eściowe.
Wszystkie one kończa˛ swoje istnienie wraz z zakończeniem realizacji danej operacji, tzn. wtedy gdy
sterowanie ”przekroczy” znak średnika.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
8
Zapobieganie tworzeniu obiektów tymczasowych
class Wektor3f { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
public :
float
x, y;
NazWektor3f operator + ( Wektor3f W ) const { return W += ∗this ; }
Wektor3f & operator += ( const Wektor3f & W ) { x += W. x; y = W. y; return ∗this ; }
}; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wektor3f
W1, W2, W3;
W1 = W2 + W3;
Ilość obiektów tymczasowych: 2
=⇒
(W1 = W2) += W3;
Ilość obiektów tymczasowych: 0
Stosujac
˛ bardziej przemyślany zapis operacji arytmetycznych można całkowicie wyeliminować tworzenie sie˛ obiektów tymczasowych.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
9
Podsumowanie
Przy stosowaniu przeciaże
˛ ń operatorów zapis złożonych działań zazwyczaj wiaże
˛ sie˛ z powstawaniem obiektów tymczasowych. Ich liczbe˛
można prawie zawsze ograniczyć lub całkowicie je wyeliminować. Powoduje to jednak utrate˛ czytelności zapisu takiego działania.
W przypadku gdy wymagania czasowe nie sa˛ krytyczne właściwym może
być zachowanie przejrzystości zapisu kosztem efektywności wykonywanych operacji. Takie podejście jest szczególnie pomocne w poczatkowej
˛
fazie tworzenia oprogramowania, gdyż zapobiega powstawaniu przypadkowych błedów
˛
w implementowanych wzorach.
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
10
Pytania i ćwiczenia
1. Jeżeli byłaby możliwa nastepuj
˛ aca
˛ definicja konstruktora kopiujacego
˛
kopiujacego:
˛
class Klasa {
public:
Klasa( Klasa Ob ) { }
};
to jakie byłyby konsekwencje w momencie jego użycia.
2. Zakładajac,
˛ że klasa Wektor3f jest tak samo zdefiniowana jak w prezentowanym
wcześniej przykładzie, należy wyznaczyć liczbe˛ powstajacych
˛
obiektów tymczasowych dla wyrażenia:
Wr = Wa + Wb + Wc + Wd;
c 2013 Bogdan Kreczmer
Copyright Wyliczanie wyrażenia – obiekty tymczasowe
11

Podobne dokumenty