4.5Общая технология решения объектных задач
В системе Rational Rose формируется структура классов задачи. Методологией реинжиниринга [1] создается С++ проект. На всех этапах разработки поддерживается идентичность C++ и Rose проекта.
Отчет по задаче содержит:
-
Условие задачи
-
Rose модель
-
Имя класса – документация по классу
-
Имя метода
-
Предусловия
-
Постусловия
-
Семантика
-
Псевдокод метода
-
Результаты тестирования псевдокода метода
-
Use Case диаграмму использования вида
-
Sequence диаграмму вида:
-
Текст программы
-
Результаты тестирования программы.
5Перегрузка операций
Любая операция, определенная в C++, может быть перегружена для созданного вами класса. Это делается с помощью функций специального вида, называемых функциями-операциями (операторными функциями). Общий вид такой функции:
возвращаемый_тип operator # (список параметров) {тело функции},
где вместо знака # ставится знак перегружаемой операции.
Функция-операция реализуется как функция класса.
Покажем методику перегрузки операции сложения для класса Point:
Файл Point.h
// Copyright (C) 1991 - 1999 Rational Software Corporation
#if defined (_MSC_VER) && (_MSC_VER >= 1000)
#pragma once
#endif
#ifndef _INC_POINT_45A3A04300EA_INCLUDED
#define _INC_POINT_45A3A04300EA_INCLUDED
//##ModelId=45A3A04300EA
class Point
{
private:
//Координата х
//##ModelId=45A3A06E0290
double x;
//Координата y
//##ModelId=45A3A09F0271
double y;
public:
double x1, y1;
//Функция копирует закрытые данные в открытые
//##ModelId=45A510D0005D
void Show();
//##ModelId=45A3AFBD0213
Point(double _x = 0,double _y = 0):x(_x),y(_y){}; //Конструктор
//Перекрытие операции сложения
//##ModelId=45A3AFBD0224
Point operator +(Point &p);
};
Файл Point.cpp
// Copyright (C) 1991 - 1999 Rational Software Corporation
#include "Point.h"
//##ModelId=45A3AFBD0224
Point Point::operator + (Point &p)
{
return Point(x+p.x, y+p.y);
};
//##ModelId=45A510D0005D
void Point::Show()
{
x1=x; y1=y;
return;
}
#endif /* _INC_POINT_45A3A04300EA_INCLUDED
Файл Main.cpp
#include
#include "Point.h"
using namespace std;
int main()
{
Point p1(0,2),p2(-1,5); //Используется конструктор
Point p3 = p1 + p2; //Используется конструктор копирования по умолчанию
p3.Show();
cout << "(" << p3.x1 <<" , "<< p3.y1 << ")" << endl;
return 0;
}// Конец функции main
*/Мы можем теперь написать:
Point pl(0, 2). р2(-1, 5);
Point рЗ = p1 + р2;
Результатом выполнения данных операторов будет точка рЗ с координатами х = -1, у = 7.
Для инициализации объекта рЗ будет вызван конструктор копирования по умолчанию, но он нас устраивает, поскольку в классе нет полей-указателей.
5.1Перегрузка операций инкремента
Операция инкремента имеет две формы: префиксную и постфиксную. Для первой формы сначала изменяется состояние объекта в соответствии с данной операцией, а затем он (объект) используется в том или ином выражении. Для второй формы объект используется в том состоянии, которое у него было до начала операции, а потом уже его состояние изменяется.
Чтобы компилятор смог различить эти две формы операции инкремента, для них используются разные сигнатуры, например:
Point& operator ++(); // префиксный инкремент
Point operator ++(int); // постфиксный инкремент
Покажем реализацию данных операций на примере класса Point:
Point& Point::operator ++()
{
x++; y++;
return *this; //Возвращается текущее значение полей объекта
}
Point Point::operator ++(int)
{
Point old = *this;
x++; y++;
return old:
}
Обратите внимание, что в префиксной операции осуществляется возврат результата по ссылке. Это предотвращает вызов конструктора копирования для создания возвращаемого значения и последующего вызова деструктора. В постфиксной операции инкремента создается объект old. Таким образом, префиксный инкремент является более эффективной операцией, чем постфиксный инкремент.
Заметим, что ранее мы не обращали внимания на запись инкремента в заголовке цикла for. Во всех примерах использовалась постфиксная форма инкремента: for (i =0; i < n: i++). Дело в том, что пока параметр i является переменной встроенного типа, форма инкремента безразлична: программа будет работать одинаково. Ситуация меняется, если параметр i есть объект некоторого класса — в этом случае префиксная форма инкремента оказывается более эффективной. Когда мы будем использовать контейнерные классы стандартной библиотеки, параметр i в заголовке цикла очень часто будет представлять объект-итератор.
СОВЕТ
Всегда используйте префиксный инкремент для параметра цикла foi— это дает более эффективный программный код.
ПРИМЕЧАНИЕ
Все сказанное о данной операции относится также и к операции декремента.
|