ТОР 5 статей: Методические подходы к анализу финансового состояния предприятия Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века Характеристика шлифовальных кругов и ее маркировка Служебные части речи. Предлог. Союз. Частицы КАТЕГОРИИ:
|
Реализация метода Add для класса Complex.class Complex Вопрос 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" Вопрос 1.9. Перегрузка функций в C++. Перегрузка унарных и бинарных операций. Перегрузка операций + и += для класса Complex. Примеры использования. Перегрузка операторов — в программировании — один из способов реализации полиморфизма, заключающийся в возможности одновременного существования в одной области видимости нескольких различных вариантов применения оператора, имеющих одно и то же имя, но различающихся типами параметров, к которым они применяются. С++ поддерживает перегрузку операторов (operator overloading). За небольшими исключениями большинство операторов С++ могут быть перегружены, в результате чего они получат специальное значение по отношению к определенным классам. Например, класс, определяющий связанный список, может использовать оператор + для того, чтобы добавлять объект к списку. Другой класс может использовать оператор + совершенно иным способом. Когда оператор перегружен, ни одно из его исходных значений не теряет смысла. Просто для определенного класса объектов определен новый оператор. Поэтому перегрузка оператора + для того, чтобы обрабатывать связанный список, не изменяет его действия по отношению к целым числам. Для того, чтобы перегрузить оператор, необходимо определить, что именно означает оператор по отношению к тому классу, к которому он применяется. Для этого определяется функция-оператор, задающая действие оператора. Общая форма записи функции-оператора для случая, когда она является членом класса, имеет вид: тип имя_класса::operator#(список_аргументов) При перегрузке унарной операции функция-оператор не имеет параметров, а при перегрузке бинарной операции функция-оператор имеет один параметр. Во всех случаях объект, активизирующий функцию-оператор, передается неявным образом с помощью указателя this. Перегрузка операций + и += для класса Complex: class Complex 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 char* GetString() {return buff;} void operator = (const char* str) {strcpy(buff,str);} { *this = str.buff; return *this; } 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 { Класс Y наследует и имеет доступ к публичным функциям get_ij() и put_ij() класса X, но не имеет доступа к i и j, поскольку они являются частными членами X. Во всех случаях частные члены остаются частными, т. е. доступными только в том классе, в котором они объявлены. Таким образом, частные члены не могут участвовать в наследовании. В связи с тем, что частные члены не могут быть наследованы, возникает интересный вопрос: что если необходимо оставить член частным и вместе с тем позволить использовать его производным классам? Для таких целей имеется другое ключевое слово — protected (защищенный). Защищенный член подобен частному, за исключением механизма наследования. При наследовании защищенного члена производный класс также имеет к нему доступ. Таким образом, указав спецификатор доступа protected, можно позволить использовать член внутри иерархии классов и запретить доступ к нему извне этой иерархии. Например: class X { Здесь класс 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) должен иметь метод для рисования. полиморфизм: мы называем метод в этом случае при наследовании реализуется замещение метода Show() класса TPoint новой реализацией метода Show() для класса TCircle. указателю на базовый класс можно присвоить значение адреса объекта TPoint *data[N]; // правильное объявление массива фигур для реализации класса "Координатная плоскость" class TPlane { public: Не нашли, что искали? Воспользуйтесь поиском:
|