
5.4 Класс для представления функции
Для представления рассмотренной ранее функции
y = (f0(x) - y0)(f1(x) - y1) ... (fn - 1(x) - yn - 1)
fi(x) = (x - x0)(x - x1) ... (x - xi - 1)(x - xi + 1) ... (x - xn - 1)
необходимо разработать класс. Это позволит в одной программе оперировать с несколькими функциями, отличающимися данными.
Создаем новое консольное приложение и добавляем в него модуль UnitMathClass. Заголовочный файл содержит определение класса SomeFunction. Векторы, содержащие xi и yi, становятся закрытыми элементами данных, функции getXY(), y() и writeTable() объявляем как открытые функции-элементы. Кроме того, можно добавить несколько новых функций:
clear() - для очистки объекта перед заполнением новыми парами значений;
addXY() - для добавления новой пары; новые числа должны добавляться в концы соответствующих векторов;
getX() и getY() для получения соответственно значений xi и yi по их номеру;
size() для получения количества введенных пар.
Функции, по своему замыслу не меняющие объекта, должны быть описаны с модификатором const. В результате заголовочный файл будет иметь вид:
#ifndef UnitMathClass_h
#define UnitMathClass_h
#include <vector>
class SomeFunction
{
private:
std::vector<double> vx, vy;
public:
bool getXY(char *fileName);
double y(double x) const;
bool writeTable(double left, double right, double step, char *fileName) const;
void clear();
void addXY(double x, double y);
double getX(int i) const;
double getY(int i) const; int size() const;
};
#endif
В файл UnitMathClass.cpp помещаем реализацию функций-элементов класса:
#include <fstream>
#include "UnitMathClass.h"
bool SomeFunction::getXY(char *fileName)
{
std::ifstream in(fileName);
if (!in)
return false;
clear();
double x, y;
while (in >> x >> y)
{
vx.push_back(x);
vy.push_back(y);
}
return true;
}
double SomeFunction::y(double x) const
{
double result = 1;
for (unsigned int i = 0; i < vy.size(); i++)
{
double f = 1;
for (unsigned int j = 0; j < vx.size(); j++)
if (i != j)
f *= x - vx[j];
result *= f - vy[i];
}
return result;
}
bool SomeFunction::writeTable(double left, double right, double step, char *fileName) const
{
std::ofstream out(fileName);
if (!out)
return false;
for (double x = left; x < right + step; x += step)
out << x << "\t" << y(x) << "\n";
return true;
}
void SomeFunction::clear()
{
vx.clear();
vy.clear();
}
void SomeFunction::addXY(double x, double y)
{
vx.push_back(x);
vy.push_back(y);
}
double SomeFunction::getX(int i) const
{
return vx.at(i);
}
double SomeFunction::getY(int i) const
{
return vy.at(i);
}
int SomeFunction::size() const { return vx.size(); }
Основной модуль программы будет выглядеть так:
#include <iostream>
#include "UnitMathClass.h"
using namespace std;
int main(int argc, char* argv[])
{
SomeFunction f;
if (f.getXY("input.txt") && f.writeTable(0, 2, 0.5, "results.txt"))
cout << "OK";
else
cout << "Error!";
return 0;
}
Можно использовать созданный класс по-другому. Можно также создать несколько объектов-функций.
#include <iostream>
#include "UnitMathClass.h"
using namespace std;
int main(int argc, char* argv[])
{
SomeFunction f, g;
f.addXY(1, 2);
f.addXY(3, 4);
g.addXY(2, 1);
g.addXY(3, 0);
for (double x = g.getX(0); x <= g.getX(g.size() - 1); x += 0.5)
{
cout << x << "\t" << f.y(x) << "\t" << g.y(x) << "\n";
}
return 0;
}
6 Задания на самостоятельную работу
Задание 1
Реализовать программу построения таблицы функции, интерполированной с помощью полинома Лагранжа с использованием вектора структур.
Задание 2
Реализовать программу, содержащую класс для представления интерполяционного полинома Лагранжа.
Задание 3*
Спроектировать класс, предназначенный для реализации двумерного массива вещественных чисел (матрицы). Данные, заносимые в массив, размещать в динамической памяти. Реализовать несколько вариантов конструкторов, в том числе конструктор по умолчанию, конструктор копирования, а также деструктор. Обеспечить сокрытие данных. Протестировать работу массива в функции main().