Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ЯП_Си++_02_Перегрузка

.pdf
Скачиваний:
14
Добавлен:
12.02.2015
Размер:
292.88 Кб
Скачать

2.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 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){