Джесс Либерти - Освой самостоятельно С++ за 21 день.
- Название:Освой самостоятельно С++ за 21 день.
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Джесс Либерти - Освой самостоятельно С++ за 21 день. краткое содержание
В книге широко представлены возможности новейшей версии программного продукта Microsoft Visual C++. Подробно описаны средства и подходы программирования современных профессиональных приложений. Материалы книги дополнены многочисленными демонстрационными программами, в процессе разработки которых максимально используются возможности программных инструментов Microsoft Visual Studio. Особое внимание уделено новинкам версии 6.0 и новейшим технологиям объектно-ориентированного программирования, включая использование библиотеки MFC и шаблонов классов, а также создание связанных списков. Отдельное занятие посвящено вопросам объектно-ориентированного анализа и проектирования приложений. Подробно рассмотрены все средства и подходы конструирования собственных пользовательских классов.
Книга рассчитана на широкий круг читателей, интересующихся современными проблемами программирования.
Освой самостоятельно С++ за 21 день. - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
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 не было бы закомментировано, программа не прошла бы этап компиляции.
Обратите внимание, что объект, создаваемый в функции main(), не является константным и объект Frisky может вызвать метод SetAge(). Адрес этого обычного объекта передается функции FunctionTwo(), но, поскольку в объявлении функции FunctionTwo() заявлено, что передаваемый указатель должен быть константным указателем на константный объект, с этим объектом функция обращается так, как если бы он был константным!
Ссылки в качестве альтернативы
При выполнении программы, показанной в листинге 9.11, устранена необходимость создания временных копий, что сокращает число обращений к конструктору и деструктору класса, в результате чего программа работает более эффективно. В данном примере использовался константный указатель на константный объект, что предотвращало возможность изменения объекта функцией. Однако по-прежнему имеет место некоторая громоздкость синтаксиса, свойственная передаче в функции указателей.
Поскольку, как вам известно, объект никогда не бывает нулевым, внутреннее содержание функции упростилось бы, если бы ей вместо указателя передавалась ссылка. Подтверждение этим словам вы найдете в листинге 9.12.
Листинг 3.12. Передача ссылок на объекты
1: // Листинг 9.12.
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(SimploCat&)
27: {
28: cout << "Simple Cat Copy Cunstructor...\n";
29: }
30:
31: SimpleCat::~SimpleCat()
32: {
33: cout << "Simple Cat Destructor...\n";
34: }
35:
36: const SimpleCat & FunctionTwo (const SimpleCat & theCat);
37:
38: int main()
39: {
40: cout << "Making a cat...\n";
41: SimpleCat Frisky;
42: cout << "Frisky is " << Frisky.GetAge() << " years old\n";
43: int age = 5;
44: Frisky,SetAge(age);
45: cout << "Frisky is " << Frisky.GetAge() << " years old\n";
46: cout << "Calling FunctionTwo...\n";
47: FunctionTwo(Frisky);
48: cout << "Frisky is " << Frisky.GetAge() << " years old\n";
49: return 0;
50: }
51:
52: // functionTwo, passes a ref to a const object
53: const SimpleCat & FunctionTwo (const SimpleCat & theCat)
54: {
55: cout << "Function Two. Returning...\n";
56: cout << "Frisky is now " << theCat.GetAge();
57: cout << " years old \n";
58: // theCat.SetAge(8); const!
59: return theCat;
60: }
Результат:
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...
Анализ:Результат работы этой программы идентичен результату, показанному после листинга9.11. Единственное существенное изменение — функция FunctionTwo() теперь принимает и возвращает ссылки на константный объект. И вновь-таки работа со ссылками несколько проще, чем работа с указателями, хотя при этом достигается та же экономия средств и эффективность выполнения, а также обеспечивается надежность за счет использования спецификатора const.
Константные ссылки
Программисты, работающие с языком C++, обычно не видят разницы между константной ссылкой на объект SimpleCat и ссылкой на константный объект SimpleCat. Сами ссылки нельзя переназначать, чтобы они ссылались на другой объект, поэтому они всегда константны. Если к ссылке применено ключевое слово const, то это делает константным объект, с которым связана ссылка.
Когда лучше использовать ссылки, а когда - указатели
Опытные программисты безоговорочно отдают предпочтение ссылкам, а не указателям. Ссылки проще использовать, и они лучше справляются с задачей сокрытия информации, как вы видели в предыдущем примере.
Но ссылки нельзя переназначать. Если же вам нужно сначала указывать на один объект, а затем на другой, придется использовать указатель. Ссылки не могут быть нулевыми, поэтому, если существует хоть какая-нибудь вероятность того, что рассматриваемый объект может быть нулевым, вам нельзя использовать ссылку. В этом случае необходимо использовать указатель.
В качестве примера рассмотрим оператор new. Если оператор new не сможет выделить память для нового объекта, он возвратит нулевой указатель. А поскольку ссылка не может быть нулевой, вы не должны инициализировать ссылку на эту память до тех пор, пока не проверите, что она не нулевая. В следующем примере показано, как это сделать:
int *pInt = new int;
if (pInt != NULL)
int &rInt = *pInt;
В этом примере объявляется указатель pInt на значение типа int, который инициализируется областью памяти, возвращаемой оператором new. Адрес этой области памяти (в указателе pInt) тестируется, и, если он не равен значению null, указатель pInt разыменовывается. Результат разыменования переменной типа int представляет собой объект типа int, и ссылка rInt инициализируется этим объектом. Следовательно, ссылка rInt становится псевдонимом для переменной типа int, возвращаемой оператором new.
Рекомендуется: Передавайте функциям параметры как ссылке везде, где это возможно. Обеспечивайте возврат значений как ссылок везде, где это возможно. Используйте спецификатор const для защиты ссылок и указателей везде, где это возможно.
Читать дальшеИнтервал:
Закладка: