r16-06.doc

(290 KB) Pobierz
Szablon dla tlumaczy

Rozdział 16.
Dziedziczenie Zzaawansowane dziedziczenie

Jak dotądDo tej pory używaliśmy korzystaliśmy z pojedynczego i wielokrotnego dziedziczenia pojedynczego i wielokrotnego w celu stworzenia relacji typu jest-czymś.

W Z tegotym rozdzialełu dowiesz się:

·         Cczym jest zawieranie i jak je zamodelować,.

·         Cczym jest delegowanie i jak je zamodelować,.

·         Jjak zaimplementować daną klasę poprzez inną,.

·         Jjak używać dziedziczenia prywatnego dziedziczenia.

Zawieranie

Jak widzieliśmy pokazaliśmy w poprzednich przykładach, możliwe jest, by dane składowe jednej klasy obejmowały obiekty innych klas. Programiści C++ mówią wtedy, że klasa zewnętrzna zawiera klasę wewnętrzną. Tak więc klasa Employee (pracownik) może zawierać na przykład obiekt typu łańcucha (przechowujący nazwisko pracownika) oraz składowe całkowite (zawierające jego pensję i inne dane).

Listing 16.1 opisuje niekompletną, choć wciążjednakowoż użyteczną klasę String, dość podobną do klasy String zadeklarowanej w rozdziale 13. Ten listing nie dajegeneruje żadnego wynikuwydruku. Zamiast tego zostanieBędzie on jednak wykorzystanywany razem z dalszymi listingami.

Listing 16.1. Klasa String

  0:  // Listing 16.1 Klasa String

  1: 

  2:  #include <iostream>

  3:  #include <string.h>

  4:  using namespace std;

  5: 

  6: class String

  7:  {

  8:  public:

  9:     // konstruktory

10:     String();

11:     String(const char *const);

12:     String(const String &);

13:     ~String();

14: 

15:     // przeciążone operatory

16:     char & operator[](int offset);

17:     char operator[](int offset) const;

18:     String operator+(const String&);

19:     void operator+=(const String&);

20:     String & operator= (const String &),

21: 

22:     // ogólne akcesory

23:     int GetLen()const { return itsLen; }

24:     const char * GetString() const { return itsString; }

25:     static int ConstructorCount;

26: 

27:  private:

28:     String (int);         // prywatny konstruktor

29:     char * itsString;

30:     unsigned short itsLen;

31: 

32:  };

33: 

34: // domyślny konstruktor tworzący ciąg pusty (zera0 bajtów)

35:  String::String()

36:  {

37:     itsString = new char[1];

38:     itsString[0] = '\0';

39:     itsLen=0;

40:     // cout << "\tDomyslny konstruktor lancucha\n";

41:     // ConstructorCount++;

42:  }

43: 

44:  // prywatny (pomocniczy) konstruktor, używany tylko przez

45:  // metody klasy przy tworzeniu nowego, wypełnionego zerowymi

46:  // bajtami, łańcucha o zadanej długości

47:  String::String(int len)

48:  {

49:     itsString = new char[len+1];

50:     for (int i = 0; i<=len; i++)

51:        itsString[i] = '\0';

52:     itsLen=len;

53:     // cout << "\tKonstruktor String(int)\n";

54:     // ConstructorCount++;

55:  }

56: 

57:  // Zamienia tablice znaków w typ String

58:  String::String(const char * const cString)

59:  {

60:     itsLen = strlen(cString);

61:     itsString = new char[itsLen+1];

62:     for (int i = 0; i<itsLen; i++)

63:        itsString[i] = cString[i];

64:     itsString[itsLen]='\0';

65:     // cout << "\tKonstruktor String(char*)\n";

66:     // ConstructorCount++;

67:  }

68: 

69:  // konstruktor kopiującyi

70:  String::String (const String & rhs)

71:  {

72:     itsLen=rhs.GetLen();

73:     itsString = new char[itsLen+1];

74:     for (int i = 0; i<itsLen;i++)

75:        itsString[i] = rhs[i];

76:     itsString[itsLen] = '\0';

77:     // cout << "\tKonstruktor String(String&)\n";

78:     // ConstructorCount++;

79:  }

80: 

81:  // destruktor, zwalnia zaalokowaną pamięć

82:  String::~String ()

83:  {

84:     delete [] itsString;

85:     itsLen = 0;

86:     // cout << "\tDestruktor klasy String\n";

87:  }

88: 

89:  // operator równości, zwalnia istniejącą pamięć,

90:  // po czym kopiuje łańcuch i rozmiar

91:  String& String::operator=(const String & rhs)

92:  {

93:     if (this == &rhs)

94:        return *this;

95:     delete [] itsString;

96:     itsLen=rhs.GetLen();

97:     itsString = new char[itsLen+1];

98:     for (int i = 0; i<itsLen;i++)

99:        itsString[i] = rhs[i];

100:     itsString[itsLen] = '\0';

101:     return *this;

102:     // cout << "\toperator= klasy String\n";

103:  }

104: 

105:  //nie const operator indeksu, zwraca

106:  // referencję do znaku, więc można go

107:  // zmienić!

108:  char & String::operator[](int offset)

109:  {

110:     if (offset > itsLen)

111:        return itsString[itsLen-1];

112:     else

113:        return itsString[offset];

114:  }

115: 

116:  // const operator indeksu do używania z obiektami

117:  // const (patrz konstruktor kopiującyi!)

118:  char String::operator[](int offset) const

119:  {

120:     if (offset > itsLen)

121:        return itsString[itsLen-1];

122:     else

123:        return itsString[offset];

124:  }

125: 

126:  // tworzy nowy łańcuch przez dodanie do rhs

127:  // bieżącego łańcucha

128:  String String::operator+(const String& rhs)

129:  {

130:     int  totalLen = itsLen + rhs.GetLen();

131:     String temp(totalLen);

132:     int i, j;

133:     for (i = 0; i<itsLen; i++)

134:        temp[i] = itsString[i];

135:     for (j = 0; j<rhs.GetLen(); j++, i++)

136:        temp[i] = rhs[j];

137:     temp[totalLen]='\0';

138:     return temp;

139:  }

140: 

141:  // zmienia bieżący łańcuch, nie zwraca nic

142:  void String::operator+=(const String& rhs)

143:  {

144:     unsigned short rhsLen = rhs.GetLen();

145:     unsigned short totalLen = itsLen + rhsLen;

146:     String  temp(totalLen);

147:     int i, j;

148:     for (i = 0; i<itsLen; i++)

149:        temp[i] = itsString[i];

150:     for (j = 0; j<rhs.GetLen(); j++, i++)

151:        temp[i] = rhs[i-itsLen];

152:     temp[totalLen]='\0';

153:     *this = temp;

154:  }

155: 

156:   // int String::ConstructorCount = 0;

 

UWAGA              Umieść Kkod z listingu 16.1 umieść w pliku o nazwie String.hpp. Wtedy zZa każdym razem, gdy będziesz potrzebował klasy String, będziesz mógł dołączyć listing 16.1 (używając instrukcji #include "String.hpp";, tak jak to robimy w dalszych listingach przedstawionych w tym rozdziale).

 

Wynik:

Brak

 

Analiza:

Listing 16.1 zawiera klasę String, bardzo podobną do klasy String z listingu 13.12 przedstawionego w rozdziale trzynastym, „Tablice i listy połączone”. Najważniejszą różnicą jest to, żeJednakże konstruktory i inne funkcje z listingu 13.12 zawierały instrukcje wypisujące na ekranie komunikaty na ekranie; w listingu 16.1 instrukcje te zostały wykomentowane. Z funkcji tych skorzystamy w następnych przykładach.

W linii 25. została zadeklarowana statyczna zmienna składowa ConstructorCount (licznik konstruktorów), która jest inicjalizowana w linii 156. Ta zmienna jestpodlega inkrementacji inicjalizowana w każdym konstruktorze klasy. Wszystko to zostało na razie wykomentowane; skorzystamy z tego dopiero w następnych listingach.

Listing 16.2 przedstawia klasę Employee (pracownik), zawierającą trzy obiekty typu String.

Listing 16.2. Klasa Employee i program sterujący

  0:  // Listing 16.2 Klasa Employee i program sterujący

  1:  #include "String.hpp"

  2: 

  3:  class Employee

  4:  {

  5:  public:

  6:     Employee();

  7:     Employee(char *, char *, char *, long);

  8:     ~Employee();

  9:     Employee(const Employee&);

10:     Employee & operator= (const Employee &);

11: 

12:     const String & GetFirstName() const

13:        { return itsFirstName; }

14:     const String & GetLastName() const { return itsLastName; }

15:     const String & GetAddress() const { return itsAddress; }

16:     long GetSalary() const { return itsSalary; }

17: 

18:     void SetFirstName(const String & fName)

19:        { itsFirstName = fName; }

20:     void SetLastName(const String & lName)

21:        { itsLastName = lName; }

22:     void SetAddress(const String & address)

23:        { itsAddress = address; }

24:     void SetSalary(long salary) { itsSalary = salary; }

25:  private:

26:     String    itsFirstName;

27:     String    itsLastName;

28:     String    itsAddress;

29:     long      itsSalary;

30:  };

31: 

32:  Employee::Employee():

33:     itsFirstName(""),

34:     itsLastName(""),

35:     itsAddress(""),

36:     itsSalary(0)

37:  {}

38: 

39:  Employee::Employee(char * firstName, char * lastName,

40:     char * address, long salary):

41:     itsFirstName(firstName),

42:     itsLastName(lastName),

43:     itsAddress(address),

44:     itsSalary(salary)

45:  {}

46: 

47:  Employee::Employee(const Employee & rhs):

48:     itsFirstName(rhs.GetFirstName()),

49:     itsLastName(rhs.GetLastName()),

50:     itsAddress(rhs.GetAddress()),

51:     itsSalary(rhs.GetSalary())

52:  {}

53: 

54:  Employee::~Employee() {}

55: 

56:  Employee & Employee::operator= (const Employee & rhs)

57:  {

58:     if (this == &rhs)

...

Zgłoś jeśli naruszono regulamin