Передача объекта как значения

В листинге 15.3 показано, как создание одного объекта Employee приводит к вызову пяти конструкторов класса String. Листинг 15.4 — это еще один переписанный вариант программы. В нем нет дополнительных операторов вывода помимо представленных в листинге 15.1 (сейчас они разблокированы) и используется статическая переменная-член ConstructorCount, объявленная в классе String.

Как следует из объявления в листинге 15.1, значение переменной ConstructorCount увеличивается на единицу при каждом вызове конструктора класса String. В конце программы, представленной в листинге 15.4, объект Employee передается на печать сначала как ссылка, а затем как значение. Статическая переменная-член ConstructorCount отслеживает, сколько объектов класса String создается при разных способах передачи объекта Employee как параметра функции.

Примечание: Перед компиляцией этого листинга в программе листинга 15.1 дополнительно к тем строкам, которые были разблокированы для листинга 15.3, следует снять символы комментариев со строк 23, 39, 52, 64, 76 и 153.

Листинг 15.4. Передача объекта как значения

1: #include "String.hpp"

2:

3: class Employee

4: {

5:

6: public:

7: Employee();

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

9: ~Employee();

10: Employee(const Employee&);

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

12:

13: const String & GetFirstName() const

14: { return itsFirstName; }

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

16: const String & GetAddress() const { return itsAddress;

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

18:

19: void SetFirstName(const String & fName)

20: { itsFirstName = fName; }

21: void SetLastName(const String & lName)

22: { itsLastName = lName; }

23: void SetAddress(const String & address)

24: { itsAddress = address; }

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

26: private:

27: String itsFirstName;

28: String itsLastName;

29: String itsAddress;

30: long itsSalary;

31: };

32:

33: Employee::Employee();

34: itsFirstName(""),

35: itsLastName(""),

36: itsAddress(""),

37: itsSalary(0)

38: { }

39:

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

41: char * address, long salary):

42: itsFirstName(firstName),

43: itsLastName(lastName),

44: itsAddress(address),

45: itsSalary(salary)

46: { }

47:

48: Employee::Employee(const Employee & rhs):

49: itsFirstName(rhs.GetFi rstName()),

50: itsLastName(rhs.GetLastName()),

51: itsAddress(rhs.GetAddress()),

52: itsSalary(rhs.GetSalary())

53: { }

54:

55: Employee::~Employee() { }

56:

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

58: {

59: if (this == &rhs)

60: return *this;

61:

62: itsFirstName = rhs.GetFirstName();

63: itsLastName = rhs.GetLastName();

64: itsAddress = rhs.GetAddress();

65: itsSalary = rhs.GetSalary();

66:

67: return *this;

68: }

69:

70: void PrintFunc(Employee);

71: void rPrintFuno(const Employee&):

72:

73: int main()

74: {

75: Employee Edie("Jane","Doe","1461 Shore Parkway", 20000);

76: Edie.SetSalary(20000);

77: Edie.SetFirstName("Edythe");

78: String LastName("Levine");

79: Edie.SetLastName(LastName); 80:

81: cout << "Constructor count: " ;

82: cout << String;:ConstruotorCount << endl;

83: rPrintFunc(Edie);

84: cout << "Constructor count: ";

85: cout << String::ConstructorCount << endl;

86: PrintFunc(Edie);

87: cout << "Constructor count: ";

88: cout << String::ConstructorCount << endl;

89: return 0;

90: }

91: void PrintFunc (Employee Edie)

92: {

93:

94: cout << "Name: ";

95: cout << Edie.GetFirstName().GetString();

96: cout << " " << Edie.GetLastName().GetString();

97: cout << ".\nAddress: ";

98: cout << Edie.GetAddress().GetString();

99: cout << ".\nSalary: " ;

100: cout << Edie.GetSalary();

101: cout << endl;

102:

103: }

104:

105: void rPrintFunc (const Employee& Edie)

106: {

107: cout << "Name: ";

108: cout << Edie.GetFirstName().GetString();

109: cout << " " << Edie.GetLastName().GetString();

110: cout << "\nAddress: ";

111: cout << Edie.GetAddress().GetString();

112: cout << "\nSalary: " ;

113: cout << Edie.GetSalary();

114: cout << endl;

115: }

Результат:

String(char*) constructor

String(char*) constructor

String(char*) constructor

String(char*) constructor

String destructor

String(char*) constructor

Constructor count: 5

Name: Edythe Levine

Address: 1461 Shore Parkway

Salary: 20000

Constructor count; 5

String(String&) constructor

String(String&) constructor

String(String&) constructor

Name: Edythe Levine

Address: 1461 Shore Parkway

Salary: 20000

String destructor

String destructor

String destructor

Constructor count: 8

String destructor

String destructor

String destructor

String destructor

Анализ: Как видно по данным, выводимым программой, в процессе создания одного объекта Employee создается пять объектов класса String. Когда объект Employee передается в функцию rPrintFunc() как ссылка, дополнительные объекты Employee не создаются. Соответственно не создаются и дополнительные объекты String. (Все они, кстати, также автоматически передаются как ссылки.)

Когда объект Employee передается в функцию PrintFunc() как значение, создается копия объекта Employee вместе с тремя объектами класса String (для этого используется конструктор-копировщик).

Наши рекомендации