Упражнения 2. Перегрузка операций
2.1. Перегрузить для класса stroka одну из выбираемых по варианту (ниже) операций для четного варианта в теле класса, для нечётного вне класса.
1,2 | Вычитание строк S1-S1 | Из первого слова удалять только первое вхождение буквы второго слова, например: долото – дом = лото |
3,4 | Вычитание строк S1-S1 | Из первого слова удалять только все вхождения буквы второго слова, например: олово – слово = о |
5,6 | Вычитание строк S1-S1 | Из первого слова удалять только соответствующие вхождения буквы второго слова, например: олово – соло = во |
7,8 | Кольцевая прокрутка слова | Например S<<i “программист”<<3 = граммистпро |
9,10 | Кольцевая прокрутка слова | Например S>>i “программист”>>3 = истпрограмм |
11,12 | Префиксная ++ | ++S, добавит слева одну букву “сслово” |
13,14 | Постфиксная ++ | S++, добавит справа одну букву “словоо” |
15,16 | Префиксная -- | --S, убавит слева одну букву “лово” |
17,18 | Постфиксная -- | S--, убавит справа одну букву “слов” |
19,20 | Унарный минус картавит | -S станет “калтошка” |
21,22 | Унарный плюс грассирует | +S вместо “Прогресс Гроссерман” станет “Прррогрресс Гррроссеррман” С вероятностями 40% буква р удваивается или утраивается и с вероятностью 10% остаётся одна |
23,24 | Префиксная ++ Заика | С вероятностями 20% первая буква слова удваивается или утраивается и с вероятностью 60% остаётся одна “п-прекрассная п-п-погода не правда ли” |
25,26 | !Японский акцент | !S все буквы лзаменяются на р, а все ч и ш на сь |
2.2. Перегрузить для символа ^ (стандартная поразрядная операция исключающее ИЛИ) для операций возведения в степень X^Y, как в Бейсике.
|
|
Вариант выбирать по формуле N = Вар MOD 6 +1
Вариант N | Тип операнда X | Тип операнда Y | Тип результата |
1 | int | int | long |
2 | long | long | long |
3 | float | float | double |
4 | double | double | double |
5 | double | double | long double |
6 | complex | int | complex |
Возведение комплексного числа в целую степень осуществлять по формуле Муавра
Zm = rm(cos(m φ)+ J sin( m φ),
где r = √ (re2 + im2) – модуль
φ = arctg(im/re) - аргумент (фаза) комплексного числа.
Подготовить контрольные примеры
Лабораторная работа № 3. Разработка собственных классов
ПРИМЕРЫ Объектно-ориентированное проектирования класса
При традиционном программировании вначале разрабатывают методики расчетов и алгоритмы, а затем реализуют их путем написания кода программ, процедур и функций. Т.е. работа проводится в две стадии: - проектирование и реализация (программирование).
Аналогично при разработке и создании таких новых абстракций как классы необходима стадия объектно-ориентированного проектирования. При этом, в соответствии с целями и задачами создаваемых абстракций, необходимо продумать, спрогнозировать для будущих возможностей и задач и определить:
|
|
- нужный набор данных, описывающих свойства объектов,
- статус их доступа,
- методы, описывающие поведение объектов,
- алгоритмы их реализующие,
- средства создания, инициализации и уничтожения объектов
- интерфейс и взаимодействие объектов.
Т.е., всё это необходимо вначале придумать.
Спроектируем в пять отмеченных этапов класс Point для решения задач манипуляции точками и, возможно будущем, другими графическими объектами, на плоскости (экране компьютера).
Данные класса и статус их доступа
Каждая точка на плоскости имеет две координаты x и y. Не стоит упускать возможности использования цвета, чтобы создаваемые объекты могли иметь дополнительные отличия, что обеспечит и большую привлекательность программ создаваемых с использованием нашего класса Point.
В соответствии с общим принципом ООП желательно обеспечивать защищенность координат и цвета от внешнего доступа из других частей программы. С другой стороны, создаваемый нами класс, возможно, будет использоваться как базовый для производных классов различных плоских геометрических фигур. Координаты базовой точки, возможно, будет целесообразно использовать как точку привязки фигуры к плоскости, поэтому разрешим будущим классам-потомкам доступ к параметрам точки привязки и примем статус доступа всех параметров точки как protected.
|
|
Методы класса Point
Над точками на плоскости можно осуществлять множество различных действий: можно менять координаты и цвет, перемещать, отображать, стирать (прятать), складывать. При этом движения или перемещения точек могут быть разными:
- в нужном направлении на заданное приращение,
- в заданную точку,
- поворот вокруг другой заданной точки P.
Для перемещения на заданное приращение dp=(dx,dy) можно создать два перегруженных метода Move(point& dP) и Move(dx, dy), которые к собственным координатам объекта добавляют соответствующие приращения dp или dx и dy. В теле этих методов должны производиться следующие действия: 1. Спрятать (Hide( )) 2. сменить координаты (x+=dP.x; y+=dP.y) и 4. Отобразить в новом положении (Show( )).
Перемещения в заданную (указанную) точку - MoveTo(point& P) и MoveTo(int xn, int yn) отличаются от предыдущих просто сменой собственных координат объекта x=P.x; y=P.y .
Для поворота данной (текущей) точки вокруг другой заданной точки P на угол φ, назовем метод Rot (от слова Rotation) необходимо рассчитать новые координаты точки (xн, yн). Для этого воспользуемся готовыми формулами, полученными путем мудреных манипуляций (т.н. аффинных преобразований) с системами координат
|
|
xн = x cos(φ) – y sin(φ) – P.x cos(φ) + P.y sin(φ) + P.x
yн = x sin(φ) + y cos(φ) – P.x sin(φ) - P.y cos(φ) + P.y (1)
Реализация ‘ этой функции на языке выглядит следующим образом.
point point::Rot(point& P, double dfi){dfi=dfi*M_PI/180; //fi в радианах
double cs=cos(dfi), sn=sin(dfi),xt,yt,a=P.GetX(), b=P.GetY();
xt= x*cs-y*sn -a*cs+b*sn+a;
yt=x*sn+y*cs -a*sn-b*cs+b;
MoveTo(xt,yt); return *this;
}//-----------------------------------------------------------
Заметим, что поскольку текущая, обрабатываемая точка (например, D.Rot(P,dfi)) должна изменить свои координаты метод должен возвращать разъименованный указатель return *thisна эту самую точку.
Для доступа к членам других объектов класса point могут потребоваться следующие публичные методы (поскольку данные нашего класса x,y,c защищенные (не public) то компилятор запрещает доступ к членам x,y,c других объектов)
int& GetX(void){return x;}
int& GetY(void){return y;}
void SetXY(int xi,int yi){ x=xi;y=yi;}
void SetC(int ci){ c=ci;}
с подходящими именами “Получить/Установить” Get/Set.
Для упрощения арифметических действий с точками перегрузим операции прибавить/отнять “+” “-”, и “дать приращение dP” - “-=”.
Для экзотики и возможного применения для будущих производных классов перегрузим постфиксную операцию инкремент для циклической смены цвета, например P++. Объект P, при этом будет переливаться всеми цветами радуги.
Для отображения и стирания наших объектов необходимы методы с соответсвующими подходящими именами Show( ) и Hide( ). Метод Show( )заключается в рисовании объекта его цветом с (для этого вначале установим цвета переднего плана = с), а метод Hide( ) – в рисовании объекта цветом фона.
Таким образом, спроектированный нами класс point на языке С++ имеет следующий набор компонентов:
class point{
protected: // на будущее для классов наследников
int x,y,c;
public:
point(int xi, int yi,int ci); //конструктор-инициализатор
point(const point& P); //конструктор-копии
int& GetX(void){return x;}
int& GetY(void){return y;}
void SetXY(int xi,int yi){ x=xi;y=yi;}
void SetC(int ci){ c=ci;}
point operator+ (point& P);
point operator- (point& P);
point& operator++(int k );
point& operator+=(point& dP); //"движок в направлении dP"
void Move(point& dP); // на приращение dp=(dx,dy)
void Move(int dx, int dy); //-----'--'--
void MoveTo(point& P); // в указанную точку
void MoveTo(int xn, int yn);
point Rot(point& P, double dfi);
void Show(void);
void Print(void); // private:
void Hide();
};//======================================================
Реализация спроектированного нами классаpoint и иллюстрация его работы см файлы point.h pointm.cpp
#include <iostream.h> #include <graphics.h> #include <conio.h>
#include <dos.h> #include "point.h"
//у класса point есть движок +=dP вариатор цвета F++ MoveTo(point p) и Move(point& dP) //на dP
void main(void){
int i,fi,gd=DETECT,gm; initgraph(&gd,&gm,"");
{
point A(100,100,BLUE), B(200,200,GREEN), C(300,300,GREEN),
E(100,200), T5(200,200,MAGENTA),dP1(1,1),TA;
for(i=0;i<10;i++);
cout<<" появились "; A.Show(); B.Show(); C.Show(); getch();
cout<<"A.Rot(B); - поворот т А вокруг B на 30 гр"<<endl;
getch(); A.Rot(B,30);
cout<<"сдвинем A в т E "; getch(); A.MoveTo(E); delay(500);
cout<<"поворот E.Rot(TT,30) - "; getch(); C.Show(); E.Rot(C,30);
getch(); cout<<"вращение т А вокруг т (300,300) на 450\n"; getch();
A.SetXY(100,100); A.SetC(BLUE);
int dfi=3;
for(fi=0;fi<450;fi+=dfi) { A.Rot(B,dfi); //A.Show();
delay(50); }
cout<<"поворот B.Rot(TT,fi) - "; getch(); B.SetC(MAGENTA);
for(fi=0;fi<450;fi+=dfi) {
C+=dP1; C.Show(); // B+=dP1;
B.Rot(C,dfi); delay(100); //радиус увелич
} getch(); //эта амплитуда совсем другая переменная
double y0=300,y,xt=5,dx=3,k=-0.5,Am=100,w=9*M_PI/(4*180);
cout<<"\nE2.MoveTo(TA) по синусоиде;"; getch();
for(i=0;i<200;i++){
y=y0+Am*sin(w*xt); xt+=dx; delay(50); //k*xt+
TA.SetXY(xt,y); A++; A.MoveTo(TA); // A.Show();
}
cout<<"\nпоследний раз"; getch();
}closegraph(); cout<<"\nСпасибо за внимание"; getch();
}//------------------------------------------------------------------
#ifndef POINTH ПРИЛОЖЕНИЕ// файл point.h
#define POINTH 1
#include <math.h> #include <iostream.h> #include <graphics.h>
#include <conio.h> #include <dos.h>
class point{
protected:
int x,y,c;
public:
point(int xi, int yi,int ci); //конструктор-инициализатор
point(const point& P); //конструктор-копии
int& GetX(void){return x;}
int& GetY(void){return y;}
void SetXY(int xi,int yi){ x=xi;y=yi;}
void SetC(int ci){ c=ci;}
point operator+ (point& P);
point operator- (point& P);
point& operator++(int k );
point& operator+=(point& dP); //движок в направлении dP
void Move(point& dP); // на приращение dp=(dx,dy)
void Move(int dx, int dy); //-----'--'--
void MoveTo(point& P); // в указанную точку
void MoveTo(int xn, int yn);
point Rot(point& P, double dfi);
void Show(void);
void Print(void);
// private:
void Hide();
};//======================================================
//Реализация методов класса point
point::point(int xi=0, int yi=0, int ci=15){x=xi; y=yi;c=ci;}
point::point(const point& P){x=P.x; y=P.y;}
void point::Show(void) {int cc=getcolor(); setcolor(c);
setfillstyle(1,c); fillellipse(x, y,2,2);
setcolor(cc); setfillstyle(1,cc);
}//-----------------------------------------------------
void point::Hide(void) {
int c1=c; c=getbkcolor();
Show(); setcolor(c=c1); // c=c1; //восст цвет
}
point point::operator+ (point& P2){
point P; P.x=x+P2.x;
P.y=y+P2.y; P.c=c; return P;
}//-----------------------
point point::operator- (point& P2){
point P; P.x=x-P2.x;
P.y=y-P2.y; P.c=c; return P;
}//-----------------------
point& point::operator++(int k ){ int c1=c%15+1;
c=c1;; return *this;}//вариатор цвета, k - заглушка
point& point::operator+=(point& P){x+=P.x; y+=P.y; return *this;}//+=движок на dP
void point::Move(point& dP) { //передвинуть на dx,dy
Hide(); x+=dP.x; y+=dP.y; Show();
}
void point::Move(int dx, int dy){
Hide(); x+=dx; y+=dy; Show();
}
void point::MoveTo(int xn, int yn) { Hide(); x=xn; y=yn; Show();
}//----------------------------------------------------
void point::MoveTo(point& P) {
Hide(); x=P.x; y=P.y; Show();
}//----------------------------------------------------
/*void point::LineTo(point& P){
int cc=getcolor(); setcolor(WHITE);
line(x,y,P.GetX(),P.GetY()); setcolor(cc);
this->Move(P.x,P.y);
// Hide(); this->x=p.GetX(); this->y=p.GetY(); Show();
}//-----------------------------------------------------*/
void point::Print(void) { cout <<"x= "<< x<<" y="<<y;}
point point::Rot(point& P, double dfi){dfi=dfi*M_PI/180;
//fi в радианах //алгоритм вращения объекта вокруг точки Р
double cs=cos(dfi), sn=sin(dfi),xt,yt,a=P.GetX(),b=P.GetY();
xt= x*cs-y*sn -a*cs+b*sn+a; //готовые формулы
yt=x*sn+y*cs -a*sn-b*cs+b;
MoveTo(xt,yt); return *this;
}//-----------------------------------------------------------
#endif
КЛАСС ЕГИПЕТСКИЕ ЧИСЛА
#include <iostream.h> // #include <string.h>
#ifndef TESTIOS // #define TESTIOS 1
char ES[]="ЦРП|\0";
class Egipt{
public:
char *Alfavit, *Data; // для строк алф и изобр числа
int Alen,Dlen; //длина строки изобр числа
int Val;
public:
Egipt(int n); //это же прототипы чего придир
Egipt(char *Dat );
Egipt(const Egipt& N);
// Egipt operator=(Egipt& N); //компилятор сам такие делает
int GetVal( ) {return Val;} //для доступа к другим
void Value();
void Kod(int n);
~Egipt();
}; //-----------------------------------------------------
Egipt::Egipt(int n):Alen(4){
int nt=n/1000,ns,nd,ne=n%10;
nd=(n%100)/10; ns=(n%1000)/100;
Dlen=nt+ns+nd+ne; Val=n; //длина строки данных
Data= new char[Dlen+1]; Data[0]='\0';
Alfavit =new char[Alen+1];
strcpy(Alfavit,ES);
this->Kod(n); //конвертер для Data
}//-----------------------------------------------------
Egipt::Egipt(char *Dat="\0"):Alen(4){
Dlen=strlen(Dat); Alfavit =new char[Alen+1];
Data=new char[Dlen+1]; strcpy(Alfavit,ES);
strcpy(Data,Dat); strcat(Data,"\0");
this->Value(); // вычисляет зн Val
}//-----------------------------------------------------
Egipt::Egipt(const Egipt& N):Alen(4){ //копия
Dlen=N.Dlen; Val=N.Val;
Data= new char[Dlen+1]; Alfavit =new char[Alen+1];
strcpy(Alfavit,ES); strcpy(Data,N.Data);
}//-----------------------------------------------------
void Egipt::Value(){ //ЦЦРРРПП
Int i=0,rez=0; char c=Data[0]; while (c!='\0'){ //дешифратор switch (c){ //кроме как здесь нигде алфавит не исполь case 'Ц': rez+=1000; break; case 'Р': rez+=100; break; case 'П': rez+=10; break; case '|': rez+=1; break; default : cout<<" нет такого символа "<<endl; }; c=Data[++i]; Val=rez; //рез присвоим член-данному Val } }//------------------------------------------------------- void Egipt::Kod(int n){ //ЦЦРРРПП
Формирует строку Data int i,nt=n/1000,ns,nd,ne=n%10; //число тыс сот дес и ед char T[2]="Ц\0",S[2]="Р\0",D[2]="П\0",E[2]="|\0"; nd=(n%100)/10; ns=(n%1000)/100; for(i=0;i<nt;i++) strcat(Data,T); //'Ц'-1000 for(i=0;i<ns;i++) strcat(Data,S); //'Р'=100 for(i=0;i<nd;i++) strcat(Data,D); //'П'=10; for(i=0;i<ne;i++) strcat(Data,E); //сформировали Data[Dlen] strcat(Data,"\0"); }//------------------------------------------------------- Egipt::~Egipt() {delete [] Data; delete [] Alfavit;}//декструктор //----------------------------------------------------- ostream& operator<<(ostream& out, Egipt N){ out<<N.Data<<" "; return out; }//----------------------------------------------------- istream& operator>>(istream& in, Egipt& N){ char *c=new char[50]; //не более 50 симв in>>c; N=Egipt(c); //неплохо иметь фильтр недоп символов delete []c; return in; }//----------------------------------------------------- #endif //--------------------------------------- #include <iostream.h> //#include <stdio.h> #include <string.h> #include <conio.h> #include <dos.h> #include "testio2.h" void main(void){ //ЦЦРРРПП
Дата добавления: 2018-04-15; просмотров: 290; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!