ЯП_Си++_02_Перегрузка
.pdf2.5. Перегрузка операции индексирования
|
|
|
|
|
|
L06_01 |
// |
time.h |
|
Только метод |
|
||
|
|
|
Не обязательно int |
|||
int& operator [] (int); |
|
|
|
|||
//--------------- |
time.cpp |
--------------- |
|
|
|
|
int& Time::operator [] (int i){ |
|
|
||||
//перегрузка операции индексирования |
|
|
||||
|
switch (i){ |
|
|
|
|
|
|
case 0: return hour; |
Плохо! Нужно исключение! |
||||
|
case 1: return minute; |
|
|
|||
|
case 2: return second; |
|
|
|||
|
default : printf("Error: out of range.\n"); exit(1); |
|||||
} |
} |
|
|
|
|
|
main.cpp |
|
|
|
|
||
//--------------- |
Можно , так как возвращает ссылку на int |
|||||
Time t (10,20,30,"1"); |
||||||
t[0] = 4; |
Если убрать & , то нельзя (т.к. вернется копия): |
|||||
printf("%i\n", t[0]); |
int operator [] (int) const; |
|||||
t[0] ≈ t.operator [](0) |
|
Лучше оба варианта, |
||||
|
|
|
второй – для константных объектов |
Что лучше для перегрузки операции: метод или глобальная дружественная функция?
Лекция №7
-При перегрузке операции «=» (а также [], (), ->) функцияоперация должна быть методом.
-Когда функция-операция реализуется как метод, левый (или единственный) операнд должен быть объектом (или ссылкой на объект) класса, для которого перегружается операция.
тип operator операция (список параметров) { тело функции }
Time t1, t2; |
|
|
|
|
Time + Time |
t1 |
+ t2 |
int(t2) |
|
Time + int |
t1 |
+ |
5 |
Time(int) |
int + Time |
5 |
+ |
t1 |
|
Ограничения на перегрузку операций:
1. |
Собственные обозначения |
|
- |
|
2. |
Что можно и что нельзя |
«sizeof» |
- |
|
|
«.» |
«.*» «?:» «::» |
||
3. |
Сохраняются |
|
|
|
|
- количество аргументов |
/ |
|
(если надо меньше – фиктивный параметр)
-приоритеты
-правила ассоциативности
4. |
Перегрузка для стандартных типов данных |
- |
5. |
Аргументы по умолчанию |
- |
6. |
Наследование |
+ (кроме =) |
7. static |
- |
|
Еще один пример |
// |
----------------String.h--------------------- |
class String{ |
|
|
private: |
|
int length; |
|
char* str; |
|
public : |
|
// конструктор преобразования / по умолчанию |
|
String(const char* = ""); |
|
// конструктор копирования |
|
String(const String &); |
|
// деструктор |
|
~String(); |
|
// перегрузка операции индексации |
|
char& operator [](int); |
|
// перегрузка операции вызова функции |
|
String operator () (int, int = 0) const; |
}; |
void print(); |
Хороший стиль программирования |
//----------------String.cpp---------------------
#include "String.h"
String::String(const char* s){ if(!s) length = 0;
else length = strlen(s); str = new char[length + 1]; if (s) strcpy(str,s);
else str = '\0';
}
String::String(const String& s){ length = s.length;
str = new char[length + 1]; strcpy(str,s.str);
}
String::~String(){ delete [] str;
}
char& String::operator [](int i){ if ((i < 0)||(i >= length)){
std::cerr << "Error: out of range." << std::endl; exit(1);
}
return str[i];
}
String String::operator()(int i, int n) const{ //перегрузка операции вызова функции – только метод!!!
if((i < 0)||(i >= length)||(n < 0)) return "";
int len;
if ((n == 0)||((i + n) > length)) len = length - i;
else
len = n;
char* s = new char[len + 1]; strncpy(s,&str[i],len); s[len] = '\0';
String ss(s); delete [] s; return ss;
}
void String::print(){
std::cout << str << std::endl;
}
//---------------- |
main.cpp--------------------- |
#include "String.h" |
int main(){ |
|
|
String s("C++"), s1 = s; |
//C++ |
|
s.print(); |
||
s1.print(); |
//C++ |
|
s[2] = '-'; |
//C+- |
|
s.print(); |
||
s(0,1).print(); |
//C |
|
s(0,1) ≈ s.operator ()(0,1) |
||
s.print(); |
//C+ |
- |
} |
|
|
// |
list.h |
Можно сделать |
||
локальный class |
||||
#ifndef LIST_H |
|
|
||
#define LIST_H |
|
|
|
|
class List{// динамический однонаправленный список |
||||
private: |
|
|
|
|
struct Elem{ |
//представление одного элемента списка |
|||
int key; |
//информативное поле |
|
||
Elem* next; //указатель на следующий элемент |
||||
}; |
|
|
|
|
Elem* first; |
|
//указатель на первый элемент списка |
||
Elem* current; |
//указатель на текущий элемент списка |
|||
public: |
|
//конструктор |
|
|
List(); |
|
|
||
virtual ~List(); |
//деструктор |
|
void operator + |
(int); |
//добавить перед текущим |
|||
void operator - |
(); |
//удалить текщий |
|||
void operator |
++ |
(); |
//переместиться на один вправо |
||
void |
operator |
-- |
(); |
//переместиться в начало |
|
void |
print(const |
char*); |
};
#endif Каких методов не хватает?
//---------------- |
list.cpp----------------------- |
|
#include "list.h" |
|
|
#include |
<stdio.h> |
|
//------- |
конструктор------- |
|
List::List(){ |
|
|
first = 0; |
|
|
current = 0; |
|
|
} |
деструктор |
|
//------- |
|
|
List::~List(){ |
//если список не пуст: first != 0 |
|
if(first){ |
||
current = first; |
|
|
while (first){ |
|
|
|
first = first->next; |
|
|
delete current; //освобождение памяти |
|
} |
current = first; |
|
} |
|
|
} |
добавить перед текущим элементом |
|
//------- |
void List::operator + (int d){