Читаем Освой самостоятельно С++ за 21 день. полностью

Наконец программа завершается и объект Frisky выходит за область видимости, генерируя последнее обращение к деструктору, выводящему свое сообщение (строка 11 в результатах работы программы).

Проанализировав работу этой программы, можно сделать вывод, что при вызове функции FunctionOne делается два обращения к конструктору копии и два обращения к деструктору, поскольку объект в эту функцию передается как значение, в то время как при вызове функции FunctionTwo подобных обращений не делается.

Передача константного указателя

Несмотря на то что передача указателя функции FunctionTwo более эффективна, чем передача по значению, она таит в себе немалую опасность. При вызове функции FunctionTwo совершенно не имелось в виду, что разрешается изменять передаваемый ей объект класса SimpleCat, задаваемый в виде адреса объекта SimpleCat. Такой способ передачи открывает объект для изменений и аннулирует защиту, обеспечиваемую при передаче объекта как значения.

Передачу объектов как значений можно сравнить с передачей музею фотографии шедевра вместо самого шедевра. Если какой-нибудь хулиган испортит фотографию, то никакого вреда при этом оригиналу нанесено не будет. А передачу объекта как ссылки можно сравнить с передачей музею своего домашнего адреса и приглашением гостей посетить ваш дом и взглянуть в вашем присутствии на драгоценный шедевр.

Решить проблему можно, передав в функцию указатель на константный объект класса SimpleCat. В этом случае к данному объекту могут применяться только константные методы, не имеющие прав на изменение объекта SimpleCat. Эта идея демонстрируется в листинге 9.11.

Листинг 9.11. Передача константных указателей

1: // Листинг 9.11.

2: // Передача константных указателей на объекты

3:

4: #include

5:

6: class SimpleCat

7: {

8:    public:

9:       SimpleCat;

10:      SimpleCat(SimpleCat&);

11:      ~SimpleCat;

12:

13:   int GetAge const { return itsAge; }

14:   void SetAge(int age) { itsAge = age; }

15:

16:   private:

17:      int itsAge;

18: };

19:

20: SimpleCat::SimpleCat

21: {

22:    cout << "Simple Cat Constructor...\n";

23:    itsAge = 1;

24: }

25:

26: SimpleCat::SimpleCat(SimpleCat&)

27: {

28:    cout << "Simple Cat Copy Constructor...\n";

29: }

30:

31: SimpleCat::~SimpleCat

32: {

33:    cout << "Simple Cat Destructor...\n";

34: }

35:

36: const SimpleCat * const FunctionTwo (const SimpleCat * const theCat);

37:

38: int main

39: {

40:    cout << "Making а cat...\n";

41:    SimpleCat Frisky;

42:    cout << "Frisky is " ;

43:    cout << Frisky.GetAge;

44:    cout << " years old\n";

45:    int age = 5:

46:    Frisky.SetAge(age);

47:    cout << "Frisky is " ;

48:    cout << Frisky.GetAge;

49:    cout << " years old \n";

50:    cout << "Calling FunctionTwo...\n";

51:    FunctionTwo(&Frisky);

52:    cout << "Frisky is ";

53:    cout << Frisky.GetAge;

54:    cout << " years_ald\n";

55:    rsturn 0;

56: }

57:

58: // functionTwo, passes a const pointer

59: const SimpleCat * const FunctionTwo (const SimpleCat * const theCat)

60: {

61:    cout << "Function Two, Returning...\n";

62:    cout << "Frisky is now " << theCat->GetAge;

63:    cout << " years old \n";

64:    // theCat->SotAge(8): const!

65:    return theCat;

66: }


Результат:

Making a cat...

Simple Cat constructor...

Frisky is 1 years old

Frisky is 5 years old

Calling FunctionTwo...

FunctionTwo. Returning...

Frisky is now 5 years old

Frisky is 5 years old

Simple Cat Destructor...


Анализ: В класс SimpleCat были добавлены две функции доступа к данным: метод GetAge (строка 13), который является константной функцией, и метод SetAge (строка 14), который не является константным. В этот класс была также добавлена переменная-член itsAge (строка 17).

Конструктор, конструктор-копировщик и деструктор по-прежнему определены для вывода на экран своих сообщений. Однако конструктор-копировщик ни разу не вызывался, поскольку объект был передан как ссылка и поэтому никаких копий объекта не создавалось. В строке 41 был создан объект со значением возраста, заданным по умолчанию. Это значение выводится на экран в строке 42.

В строке 46 переменная itsAge устанавливается с помощью метода доступа SetAge, а результат этой установки выводится на экран в строке 47. В этой программе функция FunctionOne не используется, но вызывается функция FunctionTwo, которая слегка изменена. Ее объявление занимает строку 36. На этот раз и параметр, и значение возврата объявляются как константные указатели на константные объекты.

Поскольку и параметр, и возвращаемое значение передаются как ссылки, никаких копий не создается и конструктор-копировщик не вызывается. Однако указатель в функции FunctionTwo теперь является константным, следовательно, к нему не может применяться неконстантный метод SetAge. Если обращение к методу SetAge в строке 64 не было бы закомментировано, программа не прошла бы этап компиляции.

Перейти на страницу:

Похожие книги

Сущность технологии СОМ. Библиотека программиста
Сущность технологии СОМ. Библиотека программиста

В этой книге СОМ исследуется с точки зрения разработчика C++. Написанная ведущим специалистом по модели компонентных объектов СОМ, она раскрывает сущность СОМ, помогая разработчикам правильно понять не только методы модели программирования СОМ, но и ее основу. Понимание мотивов создания СОМ и ее аспектов, касающихся распределенных систем, чрезвычайно важно для тех разработчиков, которые желают пойти дальше простейших приложений СОМ и стать по-настоящему эффективными СОМ-программистами. Показывая, почему СОМ для распределенных систем (Distributed СОМ) работает именно так, а не иначе, Дон Бокс дает вам возможность применять эту модель творчески и эффективно для ежедневных задач программирования.

Дональд Бокс

Программирование, программы, базы данных / Программирование / Книги по IT