Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Реализация метода Add для класса Complex.




class Complex
{
private:
int re, im;
public:
Complex (int x, int y) // Конструктор инициализации
{ re=x; im=y; }

void add(Complex & b);}; void add(Complex & b){ re += b.re; im += b.im;}

Вопрос 1.8. Перегрузка функций в C++. Перегрузка унарных и бинарных операций. Перегрузка операций ++с и с++ для класса Complex. Примеры использования.

Перегрузка операторов — в программировании — один из способов реализации полиморфизма, заключающийся в возможности одновременного существования в одной области видимости нескольких различных вариантов применения оператора, имеющих одно и то же имя, но различающихся типами параметров, к которым они применяются.

С++ поддерживает перегрузку операторов (operator overloading). За небольшими исключениями большинство операторов С++ могут быть перегружены, в результате чего они получат специаль­ное значение по отношению к определенным классам. Например, класс, определяющий связан­ный список, может использовать оператор + для того, чтобы добавлять объект к списку. Другой класс может использовать оператор + совершенно иным способом. Когда оператор перегружен, ни одно из его исходных значений не теряет смысла. Просто для определенного класса объектов определен новый оператор. Поэтому перегрузка оператора + для того, чтобы обрабатывать свя­занный список, не изменяет его действия по отношению к целым числам.

Для того, чтобы перегрузить оператор, необходимо определить, что именно означает опера­тор по отношению к тому классу, к которому он применяется. Для этого определяется функция-оператор, задающая действие оператора. Общая форма записи функции-оператора для случая, когда она является членом класса, имеет вид:

тип имя_класса::operator#(список_аргументов)
{
// действия, определенные применительно к классу
}

При перегрузке унарной операции функция-оператор не имеет параметров, а при перегрузке бинарной операции функция-оператор имеет один параметр. Во всех случаях объект, активизирующий функцию-оператор, передается неявным об­разом с помощью указателя this.

(Инкремент часто используется в языках программирования (равно как и в машинном языке большинства микропроцессоров), например, при организации цикла, где какая-то величина в каждом новом шаге цикла становится больше на единицу.

Для примера возьмём язык программирования JavaScript:

x++

Соответствующий ему декремент выглядит так:

x--

Оператор инкрементирования можно записывать с обеих сторон («прекремент» ++x и «посткремент» x++). От этого зависит результат операции, но не его побочного действия. Так:

var y = ++x

можно записать, как

x = x + 1 var y = x

В то время, как

var y = x++

эквивалентно

var y = x x = x + 1

--x и x-- действуют аналогично на переменную x, уменьшая её.

)

Рассмотрим, как реализуется перегрузка операции ++x и x++ на примере класса комплексных чисел. Пусть операция ++x увеличивает действительную и мнимую части комплексного числа x на 1, а x++ увеличивает на 1 только действительную часть комплексного числа x.

 

#include "stdafx.h"
#include <iostream>
using namespace std;
class complex
{
public:
complex(bool pr=true)
{
if (pr)
{
cout<<"введите x \t";
cin>>x;
cout<<"введите y \t";
cin>>y;
show_complex();
};
//функция, перегружающая оператор ++x, в этом случае
//этот метод без параметров
complex operator++()
{
//увеличиваем действительную и мнимую части на 1
x++;
y++;
//возвращаем текущий класс в качестве результата функции
return *this;
}
//функция, перегружающая оператор x++, в этом случае это
//метод с абстрактным параметром целого типа. Наличие
//целого типа в скобках говорит только о том, что
//перегружается оператор x++, а не ++x
complex operator++(int)
{
//увеличиваем действительную и мнимую части на 1
x++;
return *this;
}
//метод вывода комплексного числа на экран
void show_complex()
{
if (y>=0) cout<<x<<"+"<<y<<"i"<<endl;
else cout<<x<<y<<"i"<<endl;
};
float x;
float y;
};
int main()
{
setlocale(LC_ALL,"Rus");
//комплексное число chislo2
complex chislo2;
//увеличиваем его на 1, вызывая метод complex operator++()
++chislo2;
//вывод комплексного числа
cout<<"++chislo2 = ";
chislo2.show_complex();
//увеличиваем его на 1, вызывая метод complex operator++(int)
chislo2++;
//вывод комплексного числа
cout<<"chislo2++ = ";
chislo2.show_complex();
system("pause");
return 1;
}

Вопрос 1.9. Перегрузка функций в C++. Перегрузка унарных и бинарных операций. Перегрузка операций + и += для класса Complex. Примеры использования.

Перегрузка операторов — в программировании — один из способов реализации полиморфизма, заключающийся в возможности одновременного существования в одной области видимости нескольких различных вариантов применения оператора, имеющих одно и то же имя, но различающихся типами параметров, к которым они применяются.

С++ поддерживает перегрузку операторов (operator overloading). За небольшими исключениями большинство операторов С++ могут быть перегружены, в результате чего они получат специаль­ное значение по отношению к определенным классам. Например, класс, определяющий связан­ный список, может использовать оператор + для того, чтобы добавлять объект к списку. Другой класс может использовать оператор + совершенно иным способом. Когда оператор перегружен, ни одно из его исходных значений не теряет смысла. Просто для определенного класса объектов определен новый оператор. Поэтому перегрузка оператора + для того, чтобы обрабатывать свя­занный список, не изменяет его действия по отношению к целым числам.

Для того, чтобы перегрузить оператор, необходимо определить, что именно означает опера­тор по отношению к тому классу, к которому он применяется. Для этого определяется функция-оператор, задающая действие оператора. Общая форма записи функции-оператора для случая, когда она является членом класса, имеет вид:

тип имя_класса::operator#(список_аргументов)
{
// действия, определенные применительно к классу
}

При перегрузке унарной операции функция-оператор не имеет параметров, а при перегрузке бинарной операции функция-оператор имеет один параметр. Во всех случаях объект, активизирующий функцию-оператор, передается неявным об­разом с помощью указателя this.

Перегрузка операций + и += для класса Complex:

class Complex
{
private:
int re, im;
public:
Complex (int x, int y) // Конструктор инициализации
{ re=x; im=y; }

public static Complex add(Complex b, Complex a) { Complex g;g.re=b.re + a.re;g.im=b.re + a.im;return g; }

public static Complex operator+(Complex h, Complex n)

{

return add(h,n);

}

public static Complex operator+=(Complex h, Complex n)

{

return h = add(h,n);

}

};

Void main

{

(сюда надо пример J)

}

Вопрос 1.10. Перегрузка функций в C++. Перегрузка унарных и бинарных операций. Перегрузка оператора присваивания на примере класса String. Отличия оператора присваивания от конструктора копирования. Примеры использования.

Перегрузка операторов — в программировании — один из способов реализации полиморфизма, заключающийся в возможности одновременного существования в одной области видимости нескольких различных вариантов применения оператора, имеющих одно и то же имя, но различающихся типами параметров, к которым они применяются.

С++ поддерживает перегрузку операторов (operator overloading). За небольшими исключениями большинство операторов С++ могут быть перегружены, в результате чего они получат специаль­ное значение по отношению к определенным классам. Например, класс, определяющий связан­ный список, может использовать оператор + для того, чтобы добавлять объект к списку. Другой класс может использовать оператор + совершенно иным способом. Когда оператор перегружен, ни одно из его исходных значений не теряет смысла. Просто для определенного класса объектов определен новый оператор. Поэтому перегрузка оператора + для того, чтобы обрабатывать свя­занный список, не изменяет его действия по отношению к целым числам.

Для того, чтобы перегрузить оператор, необходимо определить, что именно означает опера­тор по отношению к тому классу, к которому он применяется. Для этого определяется функция-оператор, задающая действие оператора. Общая форма записи функции-оператора для случая, когда она является членом класса, имеет вид:

тип имя_класса::operator#(список_аргументов)
{
// действия, определенные применительно к классу
}

При перегрузке унарной операции функция-оператор не имеет параметров, а при перегрузке бинарной операции функция-оператор имеет один параметр. Во всех случаях объект, активизирующий функцию-оператор, передается неявным об­разом с помощью указателя this.

Перегрузка оператора присваивания на примере класса String.

class string
{
public:
string() {buff[0]='\0';}
string(const char* str) {strcpy(buff,str);}
~string() {}

char* GetString() {return buff;}
void SetString(const char* str) {strcpy(buff,str);}

void operator = (const char* str) {strcpy(buff,str);}
String operator=(const String& str)

{ *this = str.buff;

return *this; }
private:
char buff[MAX_LENGTH];
};

void main()

{

String str1(“def”), str2(“abc”);

str1 = str2;

// str1.buf: “abc”

}

Отличия оператора присваивания от конструктора копирования.

При работе с объектами абстрактных типов может возникнуть ситуация, когда один объект должен являться копией другого. При этом возможны два варианта.

1) Вновь создаваемый объект должен стать копией уже имеющегося.

2) Нужно скопировать один объект в другой, когда оба были созданы ране.

В первом случае используется конструктор копирования, во втором - операция присваивания.

 

Вопрос 1.11. Разработка класса Vector. Объявление (конструкторы, деструктор, перегрузка операций +, -, +=, -=, ++, --, [], =). Реализация конструкторов, деструктора, оператора присваивания.

class Vector{ double *vect; // Вектор int size; // Размерность вектораpublic: Vector(); // Конструктор по умолчанию explicit Vector(int); // Конструктор, позволяющий задавать // размерность вектора, но не являющийся // конструктором преобразования Vector(const double*, int); // Конструктор, позволяющий // проинициализировать вектор с помощью // существующего массива Vector(const Vector&); // Конструктор копирования ~Vector(); // Деструктор Vector& operator ++ (); // Увеличение всех компонент вектора // на единицу (префикс) Vector operator ++ (int); // Увеличение всех компонент вектора // на единицу (постфикс) Vector& operator -- (); // Уменьшение всех компонент вектора // на единицу (префикс) Vector operator -- (int); // Уменьшение всех компонент вектора // на единицу (постфикс) Vector& operator = (const Vector&); // Перегруженный оператор присваивания double& operator [] (int); // Перегруженный оператор индексации Vector& operator + (); // Перегруженный оператор + (унарный) Vector operator - (); // Перегруженный оператор - (унарный) Vector operator + (const Vector&); // Сложение двух векторов Vector operator + (double); // Сложение вектора с числом Vector& operator += (const Vector&);// Перегруженный оператор += для // сложения двух векторов Vector& operator += (double); // Перегруженный оператор += для // сложения вектора с числом Vector operator - (const Vector&); // Вычитание двух векторов Vector operator - (double); // Вычитание числа из вектора Vector& operator -= (const Vector&);// Перегруженный оператор -= для // вычитания двух векторов Vector& operator -= (double); // Перегруженный оператор -= для // вычитания числа из вектора};

 

#include <iostream.h>

#include <math.h>

#include "Vector.h"

 

Vector::Vector()

{ // Конструктор по умолчанию

int n;

cout << "Input array size:\t";

cin >> n; // Запрос размерности вектора

while(n <= 0) // Проверка корректности ввода

{

cout << "Input array size:\t";

cin >> n;

}

size = n;

vect = new double[size]; // Создание вектора заданной длины

}

 

Vector::Vector(int n)

{

size = n;

vect = new double[size]; // Создание вектора заданной длины

}

 

Vector::Vector(const double* v, int n)

{

size = n;

vect = new double[size];

for(int i = 0; i < size; i++)// Копирование элементов переданного массива

vect[i] = v[i]; // в компоненты вектора

}

 

Vector::Vector(const Vector& v)

{ // Конструктор копирования

size = v.size;

vect = new double[size];

for(int i = 0; i < size; i++)

vect[i] = v.vect[i];

}

 

Vector::~Vector()

{ // Деструктор

delete [] vect;

}

 

Vector& Vector::operator = (const Vector& v)

{ // Перегруженный оператор присваивания

if(&v == this) // Проверка на присваивание объекта

return *this; // самому себе

 

// Если передан другой объект, то копируем его

delete [] vect;

size = v.size;

vect = new double[size];

for(int i = 0; i < size; i++)

vect[i] = v.vect[i];

return *this;

}

};

Вопрос 1.12. Разработка класса Vector. Объявление (конструкторы, деструктор, перегрузка операций +, -, +=, -=, ++, --, [], =). Реализация операций +, +=, ++, [].

class Vector{ double *vect; // Вектор int size; // Размерность вектораpublic: Vector(); // Конструктор по умолчанию explicit Vector(int); // Конструктор, позволяющий задавать // размерность вектора, но не являющийся // конструктором преобразования Vector(const double*, int); // Конструктор, позволяющий // проинициализировать вектор с помощью // существующего массива Vector(const Vector&); // Конструктор копирования ~Vector(); // Деструктор Vector& operator ++ (); // Увеличение всех компонент вектора // на единицу (префикс) Vector operator ++ (int); // Увеличение всех компонент вектора // на единицу (постфикс) Vector& operator -- (); // Уменьшение всех компонент вектора // на единицу (префикс) Vector operator -- (int); // Уменьшение всех компонент вектора // на единицу (постфикс) Vector& operator = (const Vector&); // Перегруженный оператор присваивания double& operator [] (int); // Перегруженный оператор индексации Vector& operator + (); // Перегруженный оператор + (унарный) Vector operator - (); // Перегруженный оператор - (унарный) Vector operator + (const Vector&); // Сложение двух векторов Vector operator + (double); // Сложение вектора с числом Vector& operator += (const Vector&);// Перегруженный оператор += для // сложения двух векторов Vector& operator += (double); // Перегруженный оператор += для // сложения вектора с числом Vector operator - (const Vector&); // Вычитание двух векторов Vector operator - (double); // Вычитание числа из вектора Vector& operator -= (const Vector&);// Перегруженный оператор -= для // вычитания двух векторов Vector& operator -= (double); // Перегруженный оператор -= для // вычитания числа из вектора };

 

#include <iostream.h>

#include <math.h>

#include "Vector.h"

 

Vector& Vector::operator ++ ()

{ // Увеличение всех компонент вектора

// на единицу (префикс)

for(int i = 0; i < size; i++)

vect[i]++;

return *this;

}

 

Vector Vector::operator ++ (int n) // n - фиктивный параметр

{ // Увеличение всех компонент вектора

// на единицу (постфикс)

Vector temp(*this); // Создание временного объекта и

// инициализация его текущим объектом

// (объектом, для которого вызвалась функция)

for(int i = 0; i < size; i++)// Увеличение компонент вектора на единицу

vect[i]++; // (для текущего объекта)

return temp; // Возврат временного объекта

}

 

double& Vector::operator [] (int n)

{ // Перегруженный оператор индексации

// для проверки выхода за границы массива

if(n < 0) // В случае если индекс меньше нуля,

// то возвращаем нулевой элемент массива

{

cout << "Index of array too small:\tuse zeroth element\n";

return vect[0];

}

else if(n > size - 1) // В случае если индекс больше индекса

// последнего элемента массива,

// то возвращаем последний элемент массива

{

cout << "Index of array too big:\tuse last element\n";

return vect[size - 1];

}

else

return vect[n]; // Возврат заданного элемента массива

}

 

Vector& Vector::operator + ()

{ // Перегруженный унарный +

return *this;

}

 

Vector Vector::operator + (const Vector& v)

{ // Сложение двух векторов с помощью

// перегруженного оператора бинарный +

if(size == v.size) // Если размерности векторов совпадают

{

Vector temp(size); // Создание временного объекта

for(int i = 0; i < size; i++)

temp.vect[i] = vect[i] + v.vect[i];

return temp; // Возврат временного объекта

}

else // Если размерности векторов не совпадают

{

cout << "Different arrays sizes!!!\nArray is truncating...\n";

// Урезаем размерность большего вектора

int s = (size < v.size)? size: v.size;

Vector temp(s); // Создание временного объекта

for(int i = 0; i < s; i++)

temp.vect[i] = vect[i] + v.vect[i];

return temp; // Возврат временного объекта

}

}

 

Vector Vector::operator + (double d)

{ // Сложение вектора с числом

Vector temp(*this); // Создание временного объекта и

// инициализация его текущим объектом

// (объектом, для которого вызвалась функция)

for(int i = 0; i < size; i++)

temp.vect[i] += d;

return temp; // Возврат временного объекта

}

 

Vector& Vector::operator += (const Vector& v)

{ // Перегруженный оператор +=

// для сложения двух векторов

*this = *this + v; // Вызов функции this-<operator=(this-<operator+(v));

return *this;

}

 

Vector& Vector::operator += (double d)

{ // Перегруженный оператор +=

// для сложения вектора с числом

*this = *this + d; // Вызов функции this-<operator=(this-<operator+(d));

return *this;

}

 

Вопрос 1.13. Спецификаторы доступа в объявлении класса. Примеры. Дружественные функции на примере операции + для класса Complex.

В С++ члены класса классифицируются в соответствии с правами доступа на следующие три кате­гории: публичные (public), частные (private) и защищенные (protected). Любая функция програм­мы имеет доступ к публичным членам. Доступ к частному члену имеют только функции-члены класса или функции-друзья класса. Защищенные члены аналогичны частным членам. Разница между ними появляется только при наследовании классов.

Когда один класс наследует другой, все публичные члены базового класса становятся публич­ными членами производного класса. В противоположность этому частные члены базового класса не доступны внутри производного класса. Например, рассмотрим следующий фрагмент:

class X {
int i;
int j;
public:
void get_ij();
void put_ij();
};
class Y: public X {
int k;
public:
int get_k();
void make_k();
};

Класс Y наследует и имеет доступ к публичным функциям get_ij() и put_ij() класса X, но не имеет доступа к i и j, поскольку они являются частными членами X. Во всех случаях частные члены остаются частными, т. е. доступными только в том классе, в котором они объявлены. Таким обра­зом, частные члены не могут участвовать в наследовании.

В связи с тем, что частные члены не могут быть наследованы, возникает интересный вопрос: что если необходимо оставить член частным и вместе с тем позволить использовать его производным классам? Для таких целей имеется другое ключевое слово — protected (защищенный). Защищен­ный член подобен частному, за исключением механизма наследования. При наследовании защи­щенного члена производный класс также имеет к нему доступ. Таким образом, указав специфи­катор доступа protected, можно позволить использовать член внутри иерархии классов и запретить доступ к нему извне этой иерархии. Например:

class X {
protected:
int i;
int j;
public:
void get_ij();
void put_ij();
};
class Y: public X {
int k;
public:
int get_k();
void make_k();
};

Здесь класс Y имеет доступ к i и j, и в то же время они остаются недоступными для остальной части программы. Когда элемент объявляется защищенным, доступ к нему ограничивается, но вместе с тем можно наследовать права доступа. В отличие от этого в случае частных членов дос­туп не наследуется.

Дружественные функции на примере операции + для класса Complex.

 

class complex { private: double re, im; public: complex() { re = 0; im = 0; } complex(double r, double i) { re = r; im = i; } friend complex& operator +(complex&); }; complex complex::operator+(complex& com) { this->re = this->re + com.re; this->im = this->im + com.im; return *this;}

Вопрос 1.14. Полиморфизм на примере иерархии классов геометрических фигур. Таблица виртуальных функций. Преимущества использования полиморфизма.

Пример:

class TPoint имеет метод для рисования

void Show()

class TCircle (выведен из TPoint) должен иметь метод для рисования.

полиморфизм: мы называем метод
void Show(), сохраняя удобное и естественное название.

в этом случае при наследовании реализуется замещение метода Show() класса TPoint новой реализацией метода Show() для класса TCircle.

указателю на базовый класс можно присвоить значение адреса объекта
любого производного класса

TPoint *data[N]; // правильное объявление массива фигур для реализации класса "Координатная плоскость"

class TPlane {

public:






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных