Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Class rabbit:public living




{ protected:

int age; // используется для принятия решения о смерти кролика

public:

rabbit(int r,int c,int a=0):living(r,c),age(a){}

state who() {return RABBIT;} // отложенный метод для rabbit

living *next(world w); // отложенный метод для rabbit

void print(){cout << " кр ";}

};

 

// текущий класс - только растения

Class grass:public living

{ public:

grass(int r,int c):living(r,c){}

state who() {return GRASS;} // отложенный метод для grass

living *next(world w); // отложенный метод для grass

void print(){cout << " тр ";}

};

 

// жизнь отсутствует

Class empty: public living

{ public:

empty(int r,int c):living(r,c){}

state who() {return EMPTY;} // отложенный метод для empty

living *next(world w); // отложенный метод для empty

void print(){cout << " ";}

};

Характеристика поведения каждой формы жизни фиксируется в версии next(). Если в окрестности имеется больше grass, чем rabbit, grass остается, иначе grass будет съедена.

living *grass::next(world w)

{ int sum[STATES];

sums(w,sum);

if(sum[GRASS]>sum[RABBIT]) // кролик ест траву

return (new grass(row,col));

else

return(new empty(row,col));

}

Если возраст rabbit превышает определенное значение DRAB, он умирает либо, если поблизости много лис, он может быть съеден.

living *rabbit::next(world w)

{ int sum[STATES];

sums(w,sum);

if(sum[FOX]>=sum[RABBIT]) // лис ест кролика

return (new empty(row,col));

else if(age>DRAB) // кролик слишком старый

return(new empty(row,col));

else

return(new rabbit(row,col,age+1)); // кролик постарел

}

Fox тоже умирает от старости.

living *fox::next(world w)

{ int sum[STATES];

sums(w,sum);

if(sum[FOX]>5) // слишком много лис

return (new empty(row,col));

else if(age>DFOX) // лис слишком старый

return(new empty(row,col));

else

return(new fox(row,col,age+1)); // лис постарел

}

 

// заполнение пустой площади

living *empty::next(world w)

{ int sum[STATES];

sums(w,sum);

if(sum[FOX]>1) // первыми добавляются лисы

return (new fox(row,col));

else if(sum[RABBIT]>1) // вторыми добавляются кролики

return (new rabbit(row,col));

else if(sum[GRASS]) // третьими добавляются растения

return (new grass(row,col));

else return (new empty(row,col));// иначе пусто

}

Массив world представляет собой контейнер для жизненных форм. Он должен иметь в собственности объекты living, чтобы распределять новые и удалять старые.

// world полностью пуст

void init(world w)

{ int i,j;

for(i=0;i<N;++i)

for(j=0;j<N;++j)

w[i][j]=new empty(i,j);

}

 

// генерация исходной модели мира

void gener(world w)

{ int i,j;

for(i=0;i<N;++i)

for(j=0;j<N;++j)

{ if(i%2==0 && j%3==0) w[i][j]=new fox(i,j);

else if(i%3==0 && j%2==0) w[i][j]=new rabbit(i,j);

else if(i%5==0) w[i][j]=new grass(i,j);

else w[i][j]=new empty(i,j);

}

}

 

// вывод содержимого модели мира на экран

void pr_state(world w)

{ int i,j;

for(i=0;i<N;++i)

{ cout<<endl;

for(j=0;j<N;++j)

w[i][j]->print();

}

cout << endl;

}

 

// новый world w_new рассчитывается из старого world w_old

void update(world w_new, world w_old)

{ int i,j;

for(i=0;i<N;++i)

for(j=0;j<N;++j)

w_new[i][j]=w_old[i][j]->next(w_old);

}

 

// очистка мира

void dele(world w)

{ int i,j;

for(i=1;i<N-1;++i)

for(j=1;j<N-1;++j) delete(w[i][j]);

}

Модель имеет odd и even мир. Их смена является основой для расчета последующего цикла.

int main()

{ world odd,even;

int i;

init(odd);

init(even);

gener(even); // генерация начального мира

cout<<"1 цикл жизни модели"<<endl;

pr_state(even); // вывод сгенерированной модели

for(i=0;i<CYCLES-1;++i) //цикл моделирования

{ getch();

cout<<i+2<<" цикл жизни модели"<<endl;

if(i%2)

{ update(even,odd); // создание even модели из odd модели

pr_state(even); // вывод сгенерированной модели even

dele(odd); // удаление модели odd

}

else

{ update(odd,even); // создание odd модели из even модели

pr_state(odd); // вывод сгенерированной модели odd

dele(even); // удаление модели even

}

}

return 1;

}

 

Виртуальные деструкторы

Виртуальные деструкторы необходимы при использовании указателей на базовый класс при выделении памяти под динамически создаваемые объекты производных классов. Это обусловлено тем, что если объект уничтожается явно, например, используя операцию delete, то вызывается деструктор только класса, совпадающего с типом указателя на уничтожаемый объект. При этом не учитывается тип объекта, на который указывает данный указатель.

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

Рассмотрим отличия в работе программы при использовании виртуальных деструкторов и в случае их отсутствия на примере программы вычисляющей площади некоторых фигур (круг, прямоугольник).

#include "iostream.h"

#include "iomanip.h"

#include "string.h"

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

{protected:

float s; // площадь фигуры

public:

Shape(char *fig): s(0)

{ cout << "конструктор класса Shape (фигура "<< fig <<')'<< endl;}

virtual ~Shape()

{ cout << "деструктор класса Shape" << endl;}

void virtual print()

{cout<<s<<endl;}

void virtual area()=0;

};

class Circle: public Shape // производный класс Круг

{ int r;

public:

Circle(char *name,int r): Shape(name)

{ cout << "конструктор класса Circle "<<endl;

this->r=r;

}

~Circle()

{ cout << "деструктор класса Circle " << endl;}

void area();

};

class Bar: public Shape // производный класс Прямоугольник

{ int n,m;

public:

Bar(char *name,int n,int m): Shape(name)

{ cout << "конструктор класса Bar "<<endl;

this->n=n;

this->m=m;

}

~Bar()

{ cout << "деструктор класса Bar " << endl;}

void area();

};

 

void Circle::area()

{ s=r*r*3.14;

cout<<"Площадь круга = ";

this->print();

}

 

void Bar::area()

{ s=n*m;

cout<<"Площадь прямоугольника = ";

this->print();

}

 

int main()

{ Shape *fg1,*fg2;

 

fg1=new Circle("Круг",2);

fg2=new Bar("Прямоугольник",3,4);

 

fg1->area();

fg2->area();

delete fg1;

delete fg2;

return 1;

}

Результат работы программы:

конструктор класса Shape (фигура Circle)

конструктор класса Circle

конструктор класса Shape (фигура Bar)

конструктор класса Bar

площадь круга =12.56

площадь прямоугольника =12

деструктор класса Circle

деструктор класса Shape

деструктор класса Bar

деструктор класса Shape

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

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

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...