Организуем список из объектов класса с помощью 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 [1845 просмотров]