Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP.doc
Скачиваний:
6
Добавлен:
25.04.2019
Размер:
1.34 Mб
Скачать

4.2. Локальные классы

Кроме вложенных классов С++ позволяет вводить так называемые локальные классы. Локальными, в соответствии со стандартом языка, принято называть классы, определенные в теле функции (разница между терминами «вложенный класс» и «локальный класс», как видим, принципиальная). Назначение локальных классов – моделирование вспомогательных абстракций.

Локальный класс в целом определяется как и другие классы, однако имеется ряд ограничений. Во-первых, компоненты локального класса не могут иметь внешних определений (отсюда следует, что у локального класса не может быть статических данных). Во-вторых, функции локального класса не могут обращаться к автоматическим и регистровым переменным, локализованным в объемлющей функции. В-третьих, объемлющая функция имеет доступ только к открытой части локального класса, т.е. может обращаться исключительно к public-компонентам объектов этого класса.

В локальном классе можно разместить объявление и/или определение вложенного класса, причем последний также становится локальным. Этот вложенный класс взаимосвязан с локальным (объемлющим) классом таким же образом, как нелокальный вложенный класс со своим объемлющим классом. На уровне локального класса можно вводить отношение дружественности; например, его можно сделать дружественным к вложенному в него классу.

Ниже дан пример, иллюстрирующий особенности определения локального класса и описанные выше ограничения.

Пример

int x;

void EnclosingFunction() { // объемлющая функция

static int s = -1;

extern double d;

int x;

struct LocalClass { // определение локального класса

LocalClass() { /* операторы конструктора */ }

int fun1() { return s; }

double fun2() { return d; }

int fun3() {

return x; // ошибка, x автоматического класса памяти

}

int fun4() { return ::x; }

static int i; // ошибка, статические данные не допускаются

static void fun5() {} // статические функции допускаются

};

LocalClass oLC; // объект локального класса

...

}

Приведенный пример искусственный и не позволяет понять, «где же все-таки используются эти локальные классы». Пример, который дан ниже, более близок к практике.

Пример

#include <values.h> // для макроса MAXDOUBLE

// функция, анализирующая массивы

double ArrayAnalyserFunction(

const double * array, size_t size, size_t whatparam)

{

// whatparam определяет, какой параметр нужно рассчитать

if (array == 0 || size == 0) return MAXDOUBLE;

// MAXDOUBLE мы используем в качестве бесконечности

static const double * _internal_array = 0;

_internal_array = array;

static size_t _internal_size = 0;

_internal_size = size;

// статические переменные позволяют «обойти» ограничение на

// доступ из локального класса к автоматическим переменным

class ArrayAnalyser { // класс для анализа массивов

public:

static double Calculate(size_t whatparam) {

return

whatparam == 1 ? static_cast<double>(NumNegatives()) :

whatparam == 2 ? static_cast<double>(NumPositives()) :

whatparam == 3 ? Mean() : MeanDeviation();

}

private:

// количество отрицательных элементов

static size_t NumNegatives() {

size_t nneg = 0;

for(size_t i = 0; i < _internal_size; ++i)

nneg += _internal_array[i] < 0 ? 1 : 0;

return nneg;

}

// количество положительных элементов

static size_t NumPositives() {

size_t npos = 0;

for(size_t i = 0; i < _internal_size; ++i)

npos += _internal_array[i] > 0 ? 1 : 0;

return npos;

}

// среднее значение

static double Mean() {

double mean = 0.0;

for(size_t i = 0; i < _internal_size; ++i)

mean += _internal_array[i];

return mean / _internal_size;

}

// среднее отклонение

static double MeanDeviation() {

double mean = Mean();

double meandev = 0.0;

for(size_t i = 0; i < _internal_size; ++i)

meandev += fabs(_internal_array[i] - mean);

return meandev / (_internal_size - 1);

}

}; /* ArrayAnalyser */

// использование локального класса

return ArrayAnalyser::Calculate(whatparam);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]