Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Краткие теоретические сведения. Пусть нам необходимо найти, сколько баллов набрал спортсмен с заданной фамилией






 

Пусть нам необходимо найти, сколько баллов набрал спортсмен с заданной фамилией. Эту задачу можно отнести к классу задач «вывод по критерию». То есть каждый элемент массива, который является объектом, сравниваем с неким эталонным объектом. Если условия выполняются, то выводим объект массива. Для решения этой задачи можно создать и добавить в класс sportsmenArray типовую функцию поиска.

void sportsmenArray:: select(searchCriterion* A){

for (int i=0; i< n; i++){if(A-> result(B[i])) cout< < B[i]; }

}

Функция получает в качестве параметра некий эталонный объект. В данном объекте метод result() проверяет, удовлетворяет ли элемент массива заданному критерию и если удовлетворяет, то возвращает true. Но критериев можно придумать очень много, т.е. будет создано много разных классов для их реализации. А, как известно каждый класс это другой тип данных. Казалось бы необходимо, создавать много версий функции select c разным типом параметра для каждого эталонного объекта. Нам хотелось бы, чтобы была одна функция, в которую можно было передавать любой эталонный объект. Благодаря механизму виртуальных функций мы сможем создать одну версию функции select и не менять тип данных searchCriterion* у параметра A.

Виртуальная функция объявляется внутри базового класса и переопределяется в производном классе. В базовом классе виртуальная функция определяет вид интерфейса этой функции. Каждое переопределение этой функции в производном классе определяет ее реализацию, связанную со спецификой производного класса. Переопределяемая виртуальная функция должна иметь точно такой же тип параметров, то же их число и такой же тип возвращаемого значения, как и виртуальная функция, объявленная в базовом классе. Этим она отличается от перегружаемой функции. Для того чтобы функция стала виртуальной перед ней нужно поставить слово virtual. Виртуальная функция может вызываться также, как и любая другая функция-элемент. Однако наиболее интересен вызов виртуальной функции через указатель, благодаря чему поддерживается динамический полиморфизм. Если указатель базового класса ссылается на объект производного класса, который содержит виртуальную функцию и для которого виртуальная функция вызывается через этот указатель, то компилятор определяет, какую версию виртуальной функции вызвать, основываясь при этом на типе объекта, на который ссылается указатель. При этом определение конкретной версии виртуальной функции имеет место не в процессе компиляции, а в процессе выполнения программы. Отсюда, если два или более различных класса являются производными от базового, содержащего виртуальную функцию, то, если указатель базового класса ссылается на разные объекты этих производных классов, выполняются различные версии виртуальной функции. Т.к. мы можем для обращения к методам производного класса использовать указатель на базовый класс, то мы решаем проблему с передачей эталонного объекта в функцию.

Для нашей задачи будет базовый класс searchCriterion, который будет содержать виртуальный метод result(). Данный метод будет принимать объект типа sportsmen. Это означает, что данная иерархия классов будет работать для обработки данных о спортсменах. Каждый конкретный эталонный объект будет производным классом от класса searchCriterion. Эталонный объект будет содержать значения для сравнения. В конструкторе будет осуществляться инициализация значений. А метод result будет реализовывать алгоритм проверки, удовлетворяет ли объект типа sportsmen критерию.

class searchCriterion{//базовый класс

public:

virtual int result(sportsmen A)=0; // виртуальная функция

};

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

class findBySurname: public searchCriterion{

char surname[10]; // фамилия эталонного объекта

public: findBySurname(char* surname_){strcpy(surname, surname_); };

int result(sportsmen A){ // функция проверяет, совпадение фамилий

if(strcmp(A.get_surname(), surname)==0)return true;

else return false;

}

};

Поскольку surname – это закрытый член класс, то получить доступ к нему внутри класса findBySurname мы не можем. Нам нежелательно давать доступ к нему из класса findBySurname, т.к. значение может быть испорчено в случае ошибок, поэтому мы не будем изменять режим доступа на public либо использовать дружественные функции, а для доступа к фамилии используем метод get_surname() класса sportsmen. Т.е. в класс sportsmen мы должны добавить метод:

char * getSurname(){return surname; };

Создадим класс или эталонный объект, который будет содержать в качестве свойства базовый результат и метод, который будет проверять,, является ли результат выступления спортсмена, переданный в качестве параметра, меньше базового.

class findLessResult: public searchCriterion{

int resultValue; //базовый результат

public: findLessResult(int resultValue_){resultValue=resultValue_; };

int result(sportsmen A){//сравнение результата

if(A.get_result()< resultValue)return true;

else return false;

}

};

Проверить работу можно с помощью программного кода:

void main(){

sportsmenArray C(3);

C.inputBFile(" test"); //вводим данные из файла

C.output(); //выводим список на экран

searchCriterion *p; // создаем указатель на базовый класс

//поиск по фамилии

char surname[10];

cout< < " Input surname"; cin> > surname;

findBySurname D(surname); //инициализируем эталонный объект

p=& D; //указатель получает адрес эталонного объекта

cout< < " \nfind result\n";

C.select(p); //вызываем функцию вывода по критерию

//поиск результата, меньше базового

int baseResult;

cout< < " Input base result"; cin> > baseResult;

findLessResult D1(baseResult); //инициализируем эталонный объект

p=& D1; //указатель получает адрес объекта-критерия

C.select(p); //вызываем функцию вывода по критерию

};

 






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.