C++. Сборник рецептов
Шрифт:
// Указатель функции должен ссылаться на вспомогательную функцию, которая
// делает реальную работу. См. примеры ниже
template<typename T, typename C>
class ManipInfra {
public:
ManipInfra(basic_ostream<C>& (*pFun) (basic_ostream<C>&, T), T val) :
manipFun_(pFun), val_(val) {}
void operator(basic_ostream<C>& os) const {
manipFun_(os, val_);
} //
Вызовите функцию, задавая ее указатель и
private: // передавая ей поток и значение
T val_;
basic_ostream<С>& (*manipFun_) (basic_ostream<C>&, T);
};
template<typename T, typename C>
basic_ostream<C>& operator<<(basic_ostream<C>& os,
const ManipInfra<T, C>& manip) {
manip(os);
return(os);
}
// Вспомогательная функция, которая вызывается в итоге в классе ManipInfra
ostream& setTheWidth(ostream& os, int n) {
os.width(n);
return(os);
}
// Собственно функция манипулятора. Именно она используется в клиентском
// программном коде
ManipInfra<int, char> setWidth(int n) {
return(ManipInfra<int, char>(setTheWidth, n));
}
// Ещё одна вспомогательная функция, которая принимает аргумент типа char
ostream& setTheFillChar(ostream& os, char с) {
os.fill(c);
return(os);
}
ManipInfra<char, char> setFill(char c) {
return(ManipInfra<char, char>(setTheFillChar, c));
}
int main {
cout << setFill('-')
<< setWidth(10) << right << "Proust\n";
}
Если последовательность событий при работе этого класса все же остается неясной, я советую прогнать пример 10.5 через отладчик. Увидев его реальную работу, вы все поймете.
10.4. Создание класса, записываемого в поток
Проблема
Требуется записать класс в поток для последующего его чтения человеком или с целью его хранения в постоянной памяти, т.е. для его сериализации.
Решение
Перегрузите
operator<<
для записи в поток соответствующих данных-членов. В примере 10.6 показано, как это можно сделать. Пример 10.6. Запись объектов в поток
#include <iostream>
#include <string>
using namespace std;
class Employer {
friend ostream& operator<< // Он должен быть другом для
(ostream& out, const Employer& empr); // получения доступа к неоткрытым
public: // членам
Employer {}
~Employer {}
void setName(const string& name) {name_ = name;}
private:
string name_;
};
class Employee {
friend ostream& operator<< (ostream& out, const Employee& obj);
public:
Employee : empr_(NULL) {}
~Employee {if (empr_) delete empr_;}
void setFirstName(const string& name) {firstName_ = name;}
void setLasttName(const string& name) {lastName_ = name;}
void setEmployer(Employer& empr) {empr_ = &empr;}
const Employer* getEmployer const {return(empr_);}
private:
string firstName_;
string lastName_;
Employer* empr_;
};
// Обеспечить передачу в поток объектов
Employer... ostream& operator<<(ostream& out, const Employer& empr) {
out << empr.name_ << endl; return(out);
}
// Обеспечить передачу в поток объектов Employee...
ostream& operator<<(ostream& out, const Employee& emp) {
out << emp.firstName_ << endl;
out << emp.lastName_ << endl;
if (emp.empr_) out << *emp.empr_ << endl;
return(out);
}
int main {
Employee emp;
string first = "William";
string last = "Shatner";
Employer empr;
string name = "Enterprise";
empr.setName(name);
emp.setFirstName(first);
emp.setLastName(last);
emp.setEmployer(empr);
cout << emp; // Запись в поток
Поделиться с друзьями: