БлогNot. Организуем список из объектов класса с помощью std::vector

Организуем список из объектов класса с помощью std::vector

В этой заметке мы уже делали стандартный вектор std::vector из разнотипных объектов классов, а в лекции про полиморфизм не самым удачным образом организовывали статический массив указателей на объекты класса.

Между тем, в ситуации, когда часть объектов класса (и, возможно, классов-потомков) должна заноситься в некий список, для этого вполне можно приспособить тот же std::vector, который мы сделаем статическим свойством класса и будем хранить там указатели на нужные экземпляры класса:

static vector <Student *> vec;

Правда, при удалении адресов из списка нам придётся сравнивать адреса, а не значения, но будем исходить из того при 32- или 64-разрядной архитектуре и "плоской" адресации оперативки это действие корректно (в DOS, к примеру, из-за сегментной адресации сравнивать указатели было некорректно, а только значения).

Ниже показан пример с теми же возможностями, что в лекции, но с применением std::string вместо char * для свойства Name, что заметно упростило код, и с вектором для хранения списка.

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

Для простоты весь код приведён в одном файле .cpp, выполнялся он в консоли QT 5.X.

#include <iostream>
#include <vector>
using namespace std;

class Student {
 string Name; int Group; //приватные свойства
public:
 static vector <Student *> vec;
  //вектор для хранения адресов объектов списка
 static void print();
  //статический метод печати списка
 Student ();
 Student (string,int);
 Student (Student &);
 virtual ~Student();
 void setName (string);
 string getName ();
 void setGroup (int);
 int getGroup (void);
 void showStudent (void);
 int operator ! ();
 Student & operator += (string);
 Student & operator + (Student &);
};

vector <Student *> Student::vec;
 //инициализировать статические члены класса вне всех функций!

class Hobbit : public Student {
 char Hobby;
 public:
 Hobbit() : Student() { Hobby='1'; };
 Hobbit (Hobbit &From) : Student(From) { setHobby(From.Hobby); }
 Hobbit (string Name,int Group=0) : Student(Name,Group) { Hobby='2'; };
 Hobbit (string Name,int Group,char Hobby): Student(Name,Group) {
  this->Hobby=Hobby;
 };
 void setHobby (char Hobby) { this->Hobby = Hobby; }
 char getHobby () { return this->Hobby; }
 void showStudent ();
 Hobbit & operator ++ ();
 Hobbit & operator ++ (int);
};

//Код основных методов упростился за счёт применения string вместо char *
void Student::setName (string Name) { this->Name = Name; }
void Student::setGroup (int Group) { this->Group=Group; }
string Student::getName () { return Name; }
int Student::getGroup () { return Group; }

Student::Student () { Name = ""; Group = 0; }

Student::Student (string Name, int Group=0) {
 setName (Name); setGroup (Group);
}

Student::Student (Student &From) {
 setName (From.Name); setGroup (From.Group);
}

Student::~Student () {
 //Деструктор удаляет элемент из списка, если он там был
 for (size_t i=0; i<vec.size();i++)
     if (vec[i]==this) {
         vector<Student *>::iterator p = vec.begin();
         p+=i;
         vec.erase(p);
         break;
     }
}

void Student::showStudent () {
 cout << endl << (Name.size()?Name:"-") << ", " << Group;
}

int Student::operator ! () { return Name.size(); }
 //Оператор возвращает не 0, если имя не пусто

Student & Student::operator += (string Name) {
 this->Name += Name;
 return *this;
}

Student & Student::operator + (Student &s) {
 Student *temp = new Student (this->Name+s.getName(),this->getGroup()+s.getGroup());
 return *temp;
}

void Student::print() { //Печать всего списка
 cout << Student::vec.size() << " item(s):";
 for (size_t i=0; i<vec.size();i++)
  cout << endl << vec[i]->getName() << ", " << vec[i]->getGroup();
}

void Hobbit::showStudent() {
 this->Student::showStudent();
 cout << ", " << Hobby;
}

Hobbit & Hobbit::operator ++ () {
 this->setHobby (this->getHobby()+1);
 return *this;
}

Hobbit & Hobbit::operator ++ (int) {
 Hobbit *temp = new Hobbit();
 this->setHobby(this->getHobby()+1);
 *temp = *this;
  return *temp;
}

Hobbit * Construct (Hobbit &From) {
 Hobbit *NewHobbit = new
  Hobbit(From.getName(),From.getGroup(),From.getHobby());
 return NewHobbit;
}

int main () {
 Student *Vova = new Student ("Vova",0);
 Student *Petya = new Student ("Petya",113);
 Hobbit *Frodo = new Hobbit ("Frodo",114,'A');
 Hobbit *Sam= new Hobbit ("Sam",114,'B');
 Student::vec.push_back(Vova);
 Student::vec.push_back(Petya);
 Student::vec.push_back(Frodo);
 Student::vec.push_back(Sam);
 Student::print ();

 delete Sam; delete Vova; delete Petya;
 cout << "\nList after deleting: ";
 Student::print ();
 Frodo->setName("");
 cout << "\n!Frodo=" << !*Frodo;
 delete Frodo;
 cout << "\nAfter deleting !Frodo=" << !*Frodo;
 Hobbit Mike("Mike",221,'P');
 Mike+=" Robbins";
 Mike.showStudent();
 Hobbit Mike1 = Mike++;
 cout << "\nMike++=";  Mike1.showStudent();
 cout << "\nThen, Mike++=";  Mike.showStudent();
 Hobbit Mike2 = ++Mike; cout << "\n++Mike="; Mike2.showStudent();
 Student *Name = new Student ("Name",100);
 Student *SurName = new Student ("SurName",201);
 Name->showStudent(); SurName->showStudent();
 Student Sumkin = *Name + *SurName;
 cout << "\nName + SurName="; Sumkin.showStudent();
 Hobbit *Child = Construct(Mike2);
 cout << "\nConstruct";  Child->showStudent();
 delete Child;
 return 0;
}

21.03.2018, 14:12 [1762 просмотра]


теги: c++ программирование учебное список

К этой статье пока нет комментариев, Ваш будет первым