Якщо жоден з готових напередвизначених функціональних об’єктів нас не влаштовує, можна написати свій власний. В програмі 15.34 розбираються дві ситуації, коли саме цей спосіб виявляється оптимальним. Одна з них включає в себе використання алгоритму sort(), інша – алгоритму for_each().
Групу елементів дуже зручно сортувати, використовуючи відношення, задані оператором < в класі. Але інколи нам доводиться сортувати контейнер, що містить не самі об’єкти, а посилання на них. Зберігання вказівників замість об’єктів – грамотний розв’язок, особливо при зберіганні великих об’ємів інформації. Такий підхід є ефективним за рахунок уникнення копіювання кожного об’єкту при поміщенні його в контейнер. Тим не менше, проблема сортування залишається, оскільки об’єкти будуть впорядковані за адресами вказівників, а не за їх власними атрибутами.
Щоб змусити sort() працювати у випадку з контейнером вказівників так, як нам потрібно, необхідно мати окремий функціональний об’єкт, що задає метод сортування.
Як це зробити, показано в програмі 15.34. Тут задається вектор вказівників на об’єкти класу person. Об’єкти поміщаються у вектор, потім сортуються звичайним способом, що призводить до впорядкування за адресами вказівників, а не за атрибутами самих об’єктів. Це зовсім не те, що нам потрібно, крім того, сортування взагалі не справляє жодного ефекту, оскільки дані з самого початку вводилися підряд. Після цього вектор сортується за допомогою власного функціонального об’єкту comparePersons(). Він впорядковує елементи, на які посилаються вказівники, а не самі значення вказівників. В результаті об’єкти person впорядковуються в алфавітному порядку.
#include<iostream>
#include<conio>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
class person{
private:
string lastName;
string firstName;
long phoneNumber;
public:
person():lastName("__"),firstName("__"),phoneNumber(0)
{ }
person(string lana,string fina,long pho):
lastName(lana),firstName(fina),phoneNumber(pho)
{ }
friend bool operator<(const person&,const person&);
friend bool operator==(const person&,const person&);
void display() const
{cout<<endl<<lastName<<"\t "<<firstName<<"\t "<<phoneNumber;
}
long get_phone() const
{return phoneNumber;
}
};
bool operator<(const person& p1, const person& p2)
{if (p1.lastName==p2.lastName)
return (p1.firstName<p2.firstName?true:false);
else
return (p1.lastName<p2.lastName?true:false);
};
bool operator==(const person& p1, const person& p2)
{return(p1.lastName==p2.lastName &&
p1.firstName==p2.firstName? true:false);
};
//функціональний обєкт для порівняння вмісту
class comparePersons
{public:
bool operator() (const person* ptrp1,
const person* ptrp2) const
{return *ptrp1<*ptrp2; }
};
//функціональний обєкт для виводу персональних даних
//збережених у вказівниках
class displayPerson
{public:
void operator() (const person* ptrp) const
{ptrp->display(); }
};
////////////
int main()
{vector <person*> vectptrspers;
person* ptrp1=new person("Annie","Mannie",5667888);
person* ptrp2=new person("Billie","Sonny",5667889);
person* ptrp3=new person("Rymmie","Catty",5667880);
person* ptrp4=new person("Annie","Mannie",9667888);
person* ptrp5=new person("Holly","Yvette",5667888);
vectptrspers.push_back(ptrp1);//занесення даних у множину
vectptrspers.push_back(ptrp2);
vectptrspers.push_back(ptrp3);
vectptrspers.push_back(ptrp4);
vectptrspers.push_back(ptrp5);
for_each(vectptrspers.begin(),vectptrspers.end(),
displayPerson());
sort(vectptrspers.begin(),vectptrspers.end());
cout<<"\n\nVporiadkowani vkazivnyky:";
for_each(vectptrspers.begin(),vectptrspers.end(),
displayPerson());
sort(vectptrspers.begin(),vectptrspers.end(),comparePersons());
cout<<"\n\nVporiadkowani personalni dani:";
for_each(vectptrspers.begin(),vectptrspers.end(),
displayPerson());
while(!vectptrspers.empty())
{delete vectptrspers.back(); //видалення персони
vectptrspers.pop_back();//виштовхування вказівника
}
cout<<endl;
getch();
return 0;
}
Програма 15.34