Чтение онлайн

ЖАНРЫ

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

const int xlength = xmax–40; // оси должны быть чуть меньше окна

const int ylength = ymax–40;

Axis x(Axis::x,Point(20,y_orig), xlength,

xlength/x_scale, "one notch == 1");

Axis y(Axis::y,Point(x_orig, ylength+20),

ylength, ylength/y_scale, " one notch == 1");

Использование значения

xlength/x_scale
в качестве параметра, задающего
количество делений, позволяет использовать целочисленные отметки 1, 2, 3 и т.д. Выбор точки
(0,0)
в качестве начала координат является общепринятым. Если хотите, чтобы начало координат было не в центре, а, как обычно, в левом нижнем углу окна (раздел 15.6), вы легко сможете сделать это. Кроме того, для того чтобы различать оси, можно использовать цвет.

x.set_color(Color::red);

y.set_color(Color::red);

Итак, получаем результат, показанный ниже.

Такой рисунок вполне приемлем, но по эстетическим причинам стоило бы сдвинуть линии немного вниз. Кроме того, было бы неплохо отодвинуть метки оси x немного влево. Однако мы не будем этого делать, поскольку эстетический вид графика можно обсуждать до бесконечности. Одно из профессиональных качеств программиста заключается в том, чтобы знать, когда остановиться и потратить сэкономленное время на что-нибудь более полезное (например, на изучение новых методов или на сон). Помните: “лучшее — враг хорошего”.

15.3. Класс Function

Определение класса графического интерфейса

Function
приведено ниже.

struct Function:Shape {

// параметры функции не хранятся

Function(Fct f,double r1,double r2,Point orig,

int count = 100,double xscale = 25,double yscale = 25);

};

Класс

Function
является производным от класса
Shape
. Конструктор класса
Function
генерирует множество отрезков линий и хранит их в членах класса
Shape
. Эти отрезки линий аппроксимируют значения функции
f
. Значения функции
f
вычисляются count раз в точках, равномерно распределенных по интервалу
[r1:r2]
.

Function::Function(Fct f,double r1,double r2,Point xy,

int count,double xscale,double yscale)

// строит график функции f(x) для x из диапазона [r1:r2),

// используя count отрезков линий;

// начало координат (0,0) располагается в точке xy

// координаты x масштабируются множителем xscale

// координаты y масштабируются множителем yscale

{

if (r2–r1<=0) error("Неправильный диапазон");

if (count <=0) error("Отрицательное значение count");

double dist = (r2–r1)/count;

double r = r1;

for (int i = 0; i<count; ++i) {

add(Point(xy.x+int(r*xscale),xy.y–int(f(r)*yscale)));

r += dist;

}

}

Параметры

xscale
и
yscale
используются для масштабирования координат x и y соответственно. Обычно масштабирование необходимо для того, чтобы правильно расположить рисунок в окне.

Обратите внимание на то, что объект класса

Function
не хранит значения, передаваемые его конструктору, поэтому мы не можем впоследствии запросить у функции информацию о том, где находится начало координат, или перерисовать график с другими масштабирующими множителями. Этот объект просто хранит точки (в классе
Shape
) и выводит график на экран. Если бы мы хотели повысить гибкость объекта класса Function после его создания, то должны были бы хранить в нем требуемые значения (см. упр. 2).

15.3.1. Аргументы по умолчанию

Обратите внимание на способ инициализации аргументов

xscale
и
yscale
конструктора класса Function. Такой способ инициализации называют заданием аргументов по умолчанию (default arguments). Их значения используются тогда, когда при вызове значения аргументов вообще не указываются.

Function s(one,r_min,r_max,orig,n_points,x_scale,y_scale);

Function s2(slope,r_min,r_max,orig,n_points,x_scale); // нет

// yscale

Function s3(square,r_min,r_max,orig,n_points); // нет xscale,

// нет yscale

Function s4(sqrt,r_min,r_max,orig); // нет count, нет xscale,

// нет yscale

Этот фрагмент кода эквивалентен следующему:

Function s(one,r_min,r_max,orig,n_points,x_scale,y_scale);

Function s2(slope,r_min,r_max,orig,n_points,x_scale, 25);

Function s3(square,r_min,r_max,orig,n_points,25,25);

Function s4(sqrt,r_min,r_max,orig,100,25,25);

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

struct Function:Shape { // альтернатива аргументам, заданным

// по умолчанию

Function(Fct f,double r1,double r2,Point orig,

int count, double xscale,double yscale);

// масштаб переменной y по умолчанию:

Function(Fct f,double r1,double r2,Point orig,

int count, double xscale);

// масштаб переменной x и y:

Function(Fct f,double r1,double r2,Point orig,int count);

// значение count по умолчанию и масштаб x и y по умолчанию:

Function(Fct f,double r1,double r2,Point orig);

};

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

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