youSaid.GetLength()
|
- 1 «
|
": ";
|
t8:
|
|
i9 :
|
int
|
Inindex
|
=
|
0;
|
|
|
|
|
|
|
|
"9:
|
cin
|
»
|
Inindex;
|
|
at
|
zero-based position:
|
" «
|
Inindex;
|
“1:
|
cout
|
«
|
|
"Input
|
character
|
"2:
|
cout
|
|
«
|
" is:
|
" «
|
youSaid[Inindex] « endl;
|
|
|
|
"3:
|
return
|
0;
|
|
|
|
|
|
|
|
|
|
~4:
|
|
|
|
|
|
|
|
|
|
"5:
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Результат
Type a statement: Hey subscript operators[] are fabulous
Using operator[] for displaying your input:
H e y s u b s c r i p t o p e r a t o r s [ ] a r e f a b u l o u s Enter index 0 - 37: 2
Input character at zero-based position: 2 is: у
Анализ
Эта программа получает предложение, которое вы вводите, создает строку M y S trin g , использует ее, как показано в строке 61, а затем применяет цикл f o r для посимвольного вывода строки с помощью оператора индексирования ([ ]) и использования синтаксиса, как у массива (строки 64 и 65). Сам оператор ([ ]) определяется в строках 31-35, он обе спечивает прямой доступ к символу в определенной позиции, после проверки того, что требуемая позиция находится в пределах буфера c h a r* B u f f e r . ,
Реализовав оператор индексирования, вы можете улучшить версию, представленную
листинге 12.10. Это реализация одного оператора индексирования, который позволяет читать, и второго, позволяющего записывать значения в элемент динамического массива.
Вы можете реализовать два оператора индексирования: один как константную функ цию, а второй — как не константную:
char& operator [] (int nlndex); // используется для записи / изменения
// буфера по индексу
char& operator [] (int nlndex) const; // используется только для доступа
/ / к символу по индексу
328 ЗАНЯТИЕ 12. Типы операторов и их перегрузка
ВНИМАНИЕ! Константность операторов
При создании операторов важно использовать ключевое слово const. Обратите внимание, как листинг 12.10 ограничил возвращаемое значение оператора индексирования ([ ]) типом const char&. Программа работает и компилируется даже без ключевых слов const, но причина их применения в том, чтобы избежать подобного кода:
MyString sayHello("Hello World");
sayHello[2] = 'k' // ошибка: operator[] константный
При использовании ключевого слова const вы защищаете внутренний член класса MyString::Buffer от прямых модификаций извне при помощи опе ратора []. Кроме объявления возвращаемого значения как const, следует также ограничить тип функции оператора как const, чтобы обеспечить неспо собность этого оператора изменять атрибуты класса.
Как правило, желательно почаще использовать ограничение const, чтобы из бежать непреднамеренных изменений данных и повысить защиту атрибутов класса.
Компилятор достаточно интеллектуален, чтобы вызвать константную версию функции для операций чтения и не константную для операций записи в объект M y S trin g . Таким образом, вы можете (если хотите) иметь отдельные возможности в двух функциях ин дексирования. Например, одна функция регистрации записывает данные в контейнер, а другая читает их. Существуют и другие бинарные операторы (см. в табл. 12.2), которые могут быть переопределены или перегружены, но это не обсуждается далее. Однако их реализация подобна той, которая уже обсуждалась.
Другие операторы, такие как логические и побитовые операторы, следует создавать, только если они улучшат класс. Конечно, такому календарному классу, как D ate, не обя зательно реализовать логические операторы, тогда как классу, реализующему строку или число, возможно, они понадобятся часто.
Помните о цели вашего класса и способе его использования, принимая решение о пере грузке операторов или создании новых.
Оператор функции ()
Оператор (), заставляющий объекты вести себя, как функции, называется оператором функции (function operator). Они применяются в стандартной библиотеке шаблонов (STL) и, как правило, используются в алгоритмах STL. Они применимы при принятии реш е ний; такие объекты функций обычно называются унарным или бинарным предикатом (predicate), в зависимости от количества операндов. Листинг 12.11 анализирует простой объект функции, позволяя понять, что дает ему такое интригующее имя!
ЛИСТИНГ 12.11. Объект функции, созданный с использованием оператора ()_______________
#include
#include 3:using namespace std;
class CDisplay
6 : {
public:
void operator () (string Input) const
{
10: cout << Input « endl;
11: }
12: };
13:
14:int main ()
{
CDisplay mDisplayFuncObject;
// эквивалент
mDisplayFuncObject.operator () ("Display this string!");
mDisplayFuncObject ("Display this string!");
2 0 :
return 0;
22: }
Результат
Display this string!
Анализ
Строки 8-11 реализуют оператор (), который затем используется в строке 18 функции m ain (). Обратите внимание, что компилятор может использовать объект m D isp lay F u n - cOb j e c t как функцию (строка 18) при неявном преобразовании того, чему вызов операто ра () придает вид вызова функции.
Следовательно, этот оператор также называется оператором функции (), и объект C D is p la y также называется объектом функции, или функтором (functor). Более подроб ная информация по этой теме приведена на занятии 21, “Понятие объектов функций”.
С++11____________________________________________
Конструктор перемещ ения и оператор присваивания при
перемещ ении для высокоэффективного программирования
Конструктор перемещения и оператор присваивания при перемещении — это средства оптимизации производительности, которые стали частью стандарта С-н-11, гарантирую щие, что временные значения (r-значения, которые не существуют вне выражения) избегут необязательного копирования. Это особенно полезно при работе класса, который управля ет динамически распределяемым ресурсом, таким, как динамический массив или строка.
Проблема нежелательных этапов копирования
Обратите внимание на оператор суммы, реализованный в листинге 12.5, — фактически он создает копию и возвращает ее. Это же справедливо для оператора вычитания. Теперь рассмотрим, что произойдет при создании нового экземпляра класса M y S trin g , исполь зующего следующий синтаксис:
330 ЗАНЯТИЕ 12. Типы операторов и их перегрузка
Do'stlaringiz bilan baham: |