Розміри породжених об’єктів

Припустімо, що об’єкти, які зберігаються в пам’яті, мають різні розміри. Чому і коли таке може бути? Типовою причиною є створення породжених класів.

Згадаємо програму 17.6, у якій реалізувалося успадковування. Там у нас був клас employee, що виступав як базовий для класів manager, scientist та laborer. Об’єкти всіх цих трьох породжених класів мають різні розміри, оскільки містять різні об’єми даних.

Нам хотілося б записати дані зі списку, що містить всі три типи породжених об’єктів, використовуючи простий цикл і метод write() класу ofstream. Але нам потрібно знати розміри об’єктів, щоб передати їх в якості другого аргументу цієї функції.

Нехай існує масив вказівників arrap[], що зберігає посилання на об’єкти типу employee. Вказівники можуть посилатися таким чином і на всі три породжені класи. При використанні віртуальних функцій можна використовувати вирази типу:

arrap->putdata();

Тоді під час роботи програми буде поставлена на виконання версія putdata(), що відповідає об’єкту, на який посилається вказівник, а не та, що відповідає базовому класу. Але чи можна використовувати sizeof() для обчислення розміру аргументу за посиланням? Тобто, чи можна написати такий вираз

ouf.write((char*)arrap[j],sizeof(*arrap[j]);

На жаль, ні, оскільки sizeof() не є віртуальною функцією. Вона не знає, що потрібно звертатися до типу об’єкту, на який посилається вказівник, а не на тип самого вказівника. Ця функція завжди буде повертати розмір об’єкту базового класу.

 

 

Використання функції typeid()

Як же нам знайти розмір об’єкту, якщо ми маємо лише вказівник на нього? Одним з розв’язків є використання функції typeid(). Її можна використовувати для визначення класу об’єкту, підставляючи ім’я цього класу в якості аргументу sizeof().

Наш наступний приклад показує, як це все працює. Встановивши розмір об’єкту, ми можемо використати його у функції write() для запису в файл.

До програми 17.6 додамо нескладний інтерфейс користувача. Деякі специфічні методи зроблені віртуальними, щоб можна було скористатися масивом вказівників на об’єкти. В програму також включені деякі прийоми виявлення помилок, описані раніше.

Далі приведено текст програми 26.13.

#include<fstream>

#include<iostream>

#include<typeinfo> //для typeid()

#include<conio>

using namespace std;

#include<process.h> //для exit()

const int LEN=32; //максимальна довжина прізвища

const int MAXEN=100;//максимальне число працівників

enum employee_type {tmanager,tscientist,tlaborer};

/////////////

class employee

{private:

char name[LEN];

unsigned long number;

static int n;

static employee* arrap[]; //масив вказівників на клас робітника

public:

virtual void getdata()

{//cin.ignore(10,'/n');

cout<<"Vvedit pip: ";cin>>name;

cout<<"Vvedit nomer: ";cin>>number;

}

 

virtual void putdata()

{cout<<"\n PIP: "<<name;

cout<<"\n Nomer: "<<number;

}

 

virtual employee_type get_type();//одержати тип

static void add(); //додати працівника

static void display();//вивести дані про всіх

static void read();//читання з файлу

static void write(); //запис у файл

};

//статичні змінні

int employee::n;

employee* employee::arrap[MAXEN];

////////////////

class manager:public employee

{ private:

char title[LEN];

double dues;

public:

void getdata()

{employee::getdata();

cout<<"Vvedit tytul: ";cin>>title;

cout<<"Vvedit podatok: ";cin>>dues;

}

 

void putdata()

{employee::putdata();

cout<<"\n Tytul: "<<title;

cout<<"\n Podatok: "<<dues;

}

};

 

/////////////

class scientist:public employee

{private:

int pubs;

public:

void getdata()

{//реалізувати метод для цього класу

}

void putdata()

{//реалізувати метод для цього класу

 

}

};

//////////

class laborer:public employee

{

};

///////////

//додати працівника до списку

void employee::add()

{char ch;

//реалізувати меню вводу різних типів працівників

arrap[n++]->getdata();

}

 

void employee::display()

{//реалізувати меню відображення різних типів працівників

arrap[j]->putdata();

cout<<endl;

}

}

/////////

//повернення типу обєкту

employee_type employee::get_type()

{

if (typeid(*this)==typeid(manager))

return tmanager;

else if(typeid(*this)==typeid(scientist))

return tscientist;

else if(typeid(*this)==typeid(laborer))

return tlaborer;

else

{cerr<<"\n Nepravylnyj typ robitnyka ";exit(1);}

return tmanager;

}

//==============

//записати всі обєкти з памяті в файл

void employee::write()

{int size,j;

cout<<"Ide zapys "<<n<<" robitnykiv \n";

ofstream ouf;

employee_type etype;

ouf.open("EMPLOY.DAT",ios::trunc|ios::binary);

if(!ouf)

{cout<<"\nNemozlyvo vidkryty file\n";getch();return;}

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

{etype=arrap[j]->get_type();

ouf.write( (char*)&etype,sizeof(etype));

switch(etype)

{case tmanager:size=sizeof(manager);break;

case tscientist:size=sizeof(scientist);break;

case tlaborer: size=sizeof(laborer);break;

}

ouf.write((char*)arrap[j],size);

if(!ouf)

{cout<<"\nZapys u file nemozlyvyj\n";return;}

}

}

//----------

//Читання всіх даних з файлу в память

void employee::read()

{int size;

employee_type etype;

ifstream inf;

inf.open("EMPLOY.DAT",ios::binary);

if(!inf)

{cout <<"\nNemozlyvo vidkryty file\n";getch();return;}

n=0; //в памяті працівників нема

while(true)

{inf.read((char*)&etype,sizeof(etype));

if(inf.eof()) //вихід з циклу по eof

break;

if(!inf)

{cout <<"\nNemozlyvo chytaty type\n";getch();return;}

switch(etype)

{case tmanager:

arrap[n]=new manager;

size=sizeof(manager);

break;

case tscientist:

arrap[n]=new scientist;

size=sizeof(scientist);

break;

case tlaborer:

arrap[n]=new laborer;

size=sizeof(laborer);

break;

defaults:cout<<"\nNevidomyj typ u faili\n";getch();return;

}

inf.read((char*)arrap[n],size);

if(!inf)

{cout<<"\nChytanna z failu nemozlyve\n";getch();return;}

n++;

}//end while

cout<<"Ide chytanna "<<n<<" pracivnykiv\n";

}

/////////////

void main()

{char ch;

while(true)

{

cout<<"a - Dodavanna vidomostej"

"\nd - Vyvesty vidomosti pro vsih"

"\nw - Zapysaty vsi dani v fail"

"\nr - Prochytaty vsi dani z failu"

"\nx - Vyhid"

"\n Vash vybir:";

cin>>ch;

//реалізувати реакцію на ввід

} ; //end while

}

 

Програма 26.13








Дата добавления: 2015-08-26; просмотров: 596;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

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

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.03 сек.