Выбрать главу

<?xml version="1.0" encoding="UTF-8"?>

<!- Животные цирка Feldman Family Circus -->

<animalList>

 <animal>

  <name>Herby</name>

  <species>elephant</species>

  <dateOfBirth>1992-04-23</dateOfBirth>

  <veterinarian name="Dr. Hal Brown" phone="(801)595-9627"/>

  <trainer name="Bob Fisk" phone=(801)881-2260"/>

 </animal>

 <animal>

  <name>Sheldon</name>

  <species>parrot</species>

  <dateOfBirth>1998-09-30</dateOfBirth>

  <veterinarian name="Dr Kevin Wilson" phone="(801)466-6498"/>

  <trainer name="Eli Wendel" phone="(801)929-2506"/>

 </animal>

 <animal>

  <name>Dippy</name>

  <species>penguin</species>

  <dateOfBirth>2001-06-08</dateOfBirth>

  <veterinarian name= "Dr. Barbara Swayne" phone="(801)459-7746"/>

  <trainer name="Ben Waxman" phone="(801)882-3549"/>

 </animal>

</animalList>

Пример 14.2 показывает, как может выглядеть определение класса Animal. Animal имеет пять данных-членов, соответствующих кличке, виду, дате рождения, ветеринару и дрессировщику животного. Кличка и вид животного представляются строками типа std::string, дата его рождения представляется типом boost::gregorian::date из Boost.Date_Time, а его ветеринар и дрессировщик представляются экземплярами класса Contact, который определен также в примере 14.2. Пример 14.3 показывает, как можно использовать TinyXml для синтаксического анализа документа animals.xml, просмотра разобранного документа и заполнения вектора std::vector объектов Animal, используя извлеченные из документа данные.

Пример 14.2. Заголовочный файл animal.hpp

#ifndef ANIMALS_HPP_INCLUDED

#define ANIMALS_HPP_INCLUDED

#include <ostream>

#include <string>

#include <stdexcept> // runtime_error

#include <boost/date_time/gregorian/gregorian.hpp>

#include <boost/regex.hpp>

// Представляет ветеринара или дрессировщика

class Contact {

public:

 Contact() {}

 Contact(const std::string& name, const std::string& phone) :

  name_(name) {

  setPhone(phone);

 }

 std::string name() const { return name_; }

 std::string phone() const { return phone_; }

 void setName(const std::string& name) { name_ = name; }

 void setPhone(const std::string& phone) {

  using namespace std;

  using namespace boost;

  // Используйте Boost.Regex, чтобы убедиться, что телефон

  // задач в форме (ddd)ddd-dddd

  static regex pattern("\\([0-9]{3}\\)[0-9]{3}-[0-9]{4}");

  if (!regex_match(phone, pattern)) {

   throw runtime_error(string("bad phone number:") + phone);

  }

  phone_ = phone;

 }

private:

 std::string name_;

 std::string phone_;

};

// Сравнить на равенство два объекта класса Contact; используется в рецепте

// 14.9 (для полноты следует также определить operator!=)

bool operator--(const Contact& lhs, const Contact& rhs) {

 return lhs.name() == rhs.name() && lhs.phone() == rhs.phone();

}

// Записывает объект класса Contact в поток ostream

std::ostream& operator(std::ostream& out, const Contact& contact) {

 out << contact.name() << " " << contact.phone(); return out;

}

// Класс Animal представляет животное

class Animal {

public:

 // Конструктор по умолчанию класса Animal; этот конструктор будет вами

 // использоваться чаще всего Animal() {}

 // Конструирование объекта Animal с указанием свойств животного;

 // этот конструктор будет использован в рецепте 14.9

 Animal(const std::string& name,

  const std::string& species, const std::string& dob,

  const Contact& vet, const Contact& trainer) :

  name_(name), species_(species), vet_(vet), trainer_(trainer) {

   setDateOfBirth(dob)

  }

 // Функции доступа к свойствам животного

 std::string name() const { return name_; }

 std::string species() const { return species_; }

 boost::gregorian::date dateOfBirth() const { return dob_; )

 Contact veterinarian() const { return vet_; }

 Contact trainer() const { return trainer_; }

 // Функции задания свойств животного

 void setName(const std::string& name) { name_ = name; }

 void setSpecies(const std::string& species) { species_ = species; }

 void setDateOfBirth(const std::string& dob) {

  dob_ = boost::gregorian::from_string(dob);

 }

 void setVeterinarian(const Contact& vet) { vet_ = vet; }

 void setTrainer(const Contact& trainer) { trainer_ = trainer; }

private:

 std::string name_;

 std::string species_;

 boost::gregorian::date dob_;

 Contact vet_;

 Contact trainer_;

};

// Сравнение на равенство двух объектов Animal; используется в рецепте 14.9

// (для полноты следует также определить operator!=)

bool operator==(const Animal& lhs, const Animal& rhs) {

 return lhs.name() == rhs.name() && lhs.species() == rhs.species() &&

  lhs.dateOfBirth() == rhs.dateOfBirth() &&

  lhs.veterinarian() == rhs.veterinarian() &&

  lhs.trainer() == rhs.trainer();

}

// Записывает объект Animal в поток ostream

std::ostream& operator<<(std::ostream& out, const Animal& animal) {

 out << "Animal {\n"

  << " name=" << animal.name() << ";\n"