Упражнения 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; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!