Структуры и наследование. Структуры и полиморфизм. Абстрактная структура. Перегрузка операторов в структурах. Статические методы в структурах
В данной теме на примерах показаны возможности структур в современном C++, которые ничем не уступают классам. Необходимость применения структур в современном C++ состоит в обеспечении совместимости с полезными программами, разработанными в предыдущие годы на языке C. Часто переписывание этих программ заново не имеет смысла, поскольку требует дополнительных временных и человеческих ресурсов.
Содержание
- 1. Поддерживают ли структуры наследование? Пример
- 2. Может ли структура быть абстрактной? Поддерживают ли структуры полиморфизм?
- 3. Пример, который демонстрирует применение полиморфизма в структурах
- 4. Перегрузка операторов в структуре. Структура Point. Пример
- 5. Использование статических методов в структурах. Пример
- Связанные темы
Поиск на других ресурсах:
1. Поддерживают ли структуры наследование? Пример
Да. Структуры поддерживают наследование.
В нижеследующем примере демонстрируется использование унаследованных структур. Базовая структура Worker описывает данные о работнике: имя и возраст. Производная структура WorkerAge содержит методы доступа к полям базовой структуры. Также демонстрируется:
- доступ из конструктора производной структуры к конструктору базовой структуры;
- доступ к защищенному (protected) полю базовой структуры из унаследованной структуры;
- использование указателя this для доступа к полю базовой структуры.
Как видно из примера, в новых версиях C++ структуры есть упрощенным вариантом классов.
#include <iostream> using namespace std; // Структура, описывающая данные о работнике - базовая структура struct Worker { private: string name; // внутреннее поле, имя работника public: // Конструктор Worker(string _name) { name = _name; } // Методы доступа к полю name в структуре (геттеры, сеттеры) string GetName() { return name; } void SetName(string _name) { name = _name; } protected: int age; // защищенное поле - возраст работника }; // Унаследованная структура от Worker struct WorkerAge :Worker { // Конструктор с 2 параметрами, вызывает конструктор базовой структуры WorkerAge(string _name, int _age) :Worker(_name) { age = _age; } // Конструктор с 1 параметром WorkerAge(int age) :Worker("Noname") { this->age = age; // доступ через указатель this на данную структуру } // Методы доступа к полю age int GetAge() { return age; } void SetAge(int _age) { age = _age; } }; void main() { // Методы в структурах // 1. Использование структуры Worker Worker w(""); // объявить экземпляр структуры, используется конструктор w.SetName("John"); // доступ к полю name string nm = w.GetName(); cout << nm.c_str() << endl; // 2. Использование структуры WorkerAge WorkerAge wa("Micle", 33); cout << wa.GetName().c_str() << endl; cout << wa.GetAge() << endl; }
Результат выполнения программы
John Micle 33
⇑
2. Может ли структура быть абстрактной? Поддерживают ли структуры полиморфизм?
Да может. Это означает, что в современных версиях C++ структуры поддерживают полиморфизм.
⇑
3. Пример, который демонстрирует применение полиморфизма в структурах
Как и классы, структуры поддерживают полиморфизм. В примере демонстрируется применение полиморфизма для структур, которые реализуют наследование.
Объявляется 4 структуры с именами A, B, C, D. Эти структуры образовывают иерархию наследования. Структура A есть базовой для структуры B. Структура B есть базовой для структуры C. Структура C есть базовой для структуры D.
В каждой структуре реализован метод Print(). Структура A есть базовой для структур B, C, D. В этой структуре метод Print() объявлен как чистая виртуальная функция. Такой метод не содержит тела метода. Значит, структура A есть абстрактной. Соответственно синтаксису C++, запрещено объявлять экземпляр структуры A, можно объявлять только указатель или ссылку на эту структуру.
Также в примере реализован метод PrintStruct(), который получает ссылку на базовую структуру A и вызывает виртуальный метод Print().
В функции main() демонстрируется применение полиморфизма в двух аспектах:
- с использованием указателя на базовую структуру;
- с использованием ссылки на базовую структуру в методе PrintStruct().
#include <iostream> using namespace std; // Структура, которая содержит чисто виртуальную функцию - абстрактная структура struct A { virtual void Print() = 0; }; // Унаследованные структуры B, C, D struct B :A { void Print() override { cout << "B.Print()" << endl; } }; struct C :B { void Print() override { cout << "C.Print()" << endl; } }; struct D :C { void Print() override { cout << "D.Print()" << endl; } }; // Метод, получающий ссылку на базовую структуру // и вызывает метод Print() этой структуры void PrintStruct(A& refA) { refA.Print(); // вызвать метод Print() } void main() { // Демонстрация поддержки полиморфизма в структурах // 1. Объявить внутренние переменные A* pA; // указатель на базовую структуру A B objB; // экземпляр структуры B C objC; // экземпляр структуры C D objD; // экземпляр структуры D // 1. Вызов метода Print() единым способом (интерфейсом) // с помощью указателя, который указывает на разные экземпляры структур pA = &objB; // перенаправить указатель на экземпляр структуры B pA->Print(); // вызов B.Print() pA = &objC; pA->Print(); // вызов C.Print() pA = &objD; pA->Print(); // вызов D.Print() // 2. Передача ссылки на структуру A в метод PrintStruct() cout << "-----------------------------------------------------" << endl; pA = &objB; PrintStruct(*pA); // вызов B.Print() PrintStruct(objB); // вызов B.Print() PrintStruct(objC); // вызов C.Print() PrintStruct(objD); // вызов D.Print() }
Результат выполнения программы
B.Print() C.Print() D.Print() ----------------------------------------------------- B.Print() B.Print() C.Print() D.Print()
⇑
4. Перегрузка операторов в структуре. Структура Point. Пример
В структурах, как и в классах, можно использовать операторные функции, перегружающие операторы. Далее приводится пример структуры Point, в которой реализована перегрузка операторов + (суммирование) и – (вычитание).
Структура Point объявляет следующие составляющие:
- общедоступные (public) переменные x, y, определяющие координаты точки на плоскости;
- два конструктора, которые инициализируют внутренние переменные;
- операторную функцию operator+(), которая перегружает оператор + (суммирование);
- операторную функцию operator–(), которая перегружает оператор – (вычитание);
- метод Print() для вывода информации о точке.
В функции main() демонстрируется использование структуры Point.
#include <iostream> using namespace std; // Структура, описывающая точку на координатной плоскости struct Point { public: double x, y; // координаты точки // Конструкторы Point() { x = y = 0; } Point(double _x, double _y) : x(_x), y(_y) { } // Перегруженный оператор + Point operator+(Point& pt) { return Point(x + pt.x, y + pt.y); } // Перегруженный оператор - Point operator-(Point& pt) { return Point(x - pt.x, y - pt.y); } // Перегруженный оператор присваивания Point operator=(Point pt) { x = pt.x; y = pt.y; return *this; } // Метод вывода информации о точке void Print(string objName) { cout << objName << ": x = " << x << ", y = " << y << endl; } }; void main() { // Демонстрация использования структуры Point Point pt1(2, 8.5); Point pt2(-5.1, 7.5); // Инициализация - тест Point pt3 = pt1; pt3.Print("pt3"); // Тест операторной функции operator+() Point pt4 = pt1 + pt2; pt4.Print("pt4"); // Тест операторной функции operator=() Point pt5; pt5 = pt3; pt5.Print("pt5"); // Тест сочетания операторных функций operator-(), operator+() Point pt6(1, 1); Point pt7(-3, -3); cout << "---------------" << endl; pt6.Print("pt6"); pt7.Print("pt7"); Point pt8 = pt6 - pt7 - pt3 + pt4; // pt8 = (-1.1, 11.5) pt8.Print("pt8"); }
⇑
5. Использование статических методов в структурах. Пример
В структурах могут использоваться статические методы и переменные. В примере реализована структура Complex, которая содержит статические методы вычисления суммы, разности, произведения и деления комплексных чисел. Также в структуре реализован метод Print(), выводящий комплексное число в удобном виде.
В функции main() демонстрируется использование статических методов класса Complex.
Текст демонстрационной программы типа ConsoleApplication следующий:
#include <iostream> using namespace std; // Структура, содержащая статические методы обработки комплексных чисел struct Complex { // Общедоступные статические методы // Суммирование комплексных чисел (a1+b1*i) + (a2+b2*i) static void Add(double a1, double b1, double a2, double b2, double& a, double& b) { a = a1 + a2; b = b1 + b2; } // Вычитание комплексных чисел static void Sub(double a1, double b1, double a2, double b2, double& a, double& b) { a = a1 - a2; b = b1 - b2; } // Умножение комплексных чисел static void Mul(double a1, double b1, double a2, double b2, double& a, double& b) { a = a1 * a2 - b1 * b2; b = a1 * b2 + b1 * a2; } // Деление комплексных чисел static void Div(double a1, double b1, double a2, double b2, double& a, double& b) { double denom = a2 * a2 + b2 * b2; // Проверка, можно ли корректно разделить два числа if (denom == 0) { a = b = 0; // установить нулевые значения return; } a = (a1 * a2 + b1 * b2) / denom; b = (a2 * b1 - a1 * b2) / denom; } // Вывод информации о комплексном числе static void Print(string text, double a, double b) { // Установить точность 2 знака после запятой cout.precision(2); cout << text << a; if (b > 0) cout << "+"; cout << b << "*i" << endl; } }; void main() { // Статические методы в структуре double a1 = 3, b1 = 2.5; double a2 = 7, b2 = -1.8; double a, b; // Вывести первое число Complex::Print("z1 = ", a1, b1); // Вывести второе число Complex::Print("z2 = ", a2, b2); // Вычислить сумму, результат в a, b Complex::Add(a1, b1, a2, b2, a, b); Complex::Print("z1 + z2 = ", a, b); // Вычислить разницу Complex::Sub(a1, b1, a2, b2, a, b); Complex::Print("z1 - z2 = ", a, b); // Вычислить произведение Complex::Mul(a1, b1, a2, b2, a, b); Complex::Print("z1 * z2 = ", a, b); // Вычислить деление комплексных чисел Complex::Div(a1, b1, a2, b2, a, b); Complex::Print("z1 / z2 = ", a, b); }
Результат выполнения программы:
z1 = 3+2.5*i z2 = 7-1.8*i z1 + z2 = 10+0.7*i z1 - z2 = -4+4.3*i z1 * z2 = 26+12*i z1 / z2 = 0.32+0.44*i
⇑
Связанные темы
- Составные типы данных. Шаблон структуры. Структурная переменная. Структуры в среде CLR. Объявление и инициализация структурной переменной
- Структуры. Использование методов в структурах. Конструкторы в структурах
⇑