Деструктор:
Код:
Book::~Book()
{
delete [] author;
delete [] nameBook;
delete [] janr;
}
Вопрос меня смущает: ежели используешь стандартную библиотеку, почему бы не использовать стандартные контейнеры? Например класс string легко превращается в char* при необходимости. С памятью они очень нежно обращаются.
Код:
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
class Book
{
public:
Book(const string& au, const string& nb, const string& jr, unsigned int yr);
Book(istream& input);// для ввода из потока
void setAuthorBook(const string& au) {author = checkLength(au);}
void setNameBook(const string& nb) {nameBook = checkLength(nb);}
void setJanreBook(const string& jr) {janr = checkLength(jr);}
void setYearBook(int yr) {year = checkYear(jr);}
const string& getAuthorBook() { return author; }
const string& getNameBook() { return nameBook; }
const string& getJanreBook() { return janr; }
unsigned int getYearBook() { return year; }
void printBook();
void calculateYearBook();
private:
string author;
string nameBook;
string janr;
unsigned int year;
static void checkLength(const string& str);
static const unsigned& checkYear(const unsigned&);
};
const Book::string& Book::checkLength(const string& str)
{
if (str.empty() || 255<=str.size())
{
throw out_of_range(
"Book::checkLength "
"a string which is empty or greater 255 chars is not permitted");
}
return str;
}
const unsigned& Book::checkYear(const unsigned& yr)
{
if (2008 <= yr)
{
throw out_of_range(
"Book::checkYear "
"year>=2008 is not permitted");
}
return str;
}
Book::Book(const string& au, const string& nb, const string& jr, unsigned int yr) :
author (checkLength(au)),
nameBook(checkLength(nb)),
janr (checkLength(jr)),
year (yr)
{
}
Book::Book(std::stream& input) :
author (),
nameBook(),
janr (),
year ()
{
// использование копирования позволяет сохранить объект в целости и сохранности
// в случае исключения. Например если при чтении любого поля возникнет ошибка,
// то следующий код оставит книгу b1 без изменений:
// Book b1(...);
// b1.setAuthorBook(...);
// ...
// try
// {
// b1 = Book(cin); // произошла ошибка при чтении года!!!
// }
// catch(runtime_error& err)
// {
// clog << "error: " << err.what() << endl;
// }
clog << "reading data from stream\n";
if (((clog << "autor [enter]: "), getline(input, author)) &&
((clog << "nameBook [enter]: "), getline(input, nameBook)) &&
((clog << "janr [enter]: "), getline(input, janr)) &&
((clog << "year [any space character]: "), (input >> jear)))
{
clog << "checking data\n";
checkLength(author);
checkLength(nameBook);
checkLength(janr);
checkYear(yr);
clog << "all ok\n";
}
else
{
throw runtime_error("error reading from stream");
}
}
// Печать объекта-------------------------------------------------------------
void Book::printBook()
{
cout<<" Author Book: "<<author<<endl;
cout<<" Name Book: "<<nameBook<<endl;
cout<<" Janre Book: "<<janr<<endl;
cout<<" Year Book: "<<year<<endl;
}
//---------------------------------------------------------------------------
void main()
{
Book b("Servantes", "Don Kixot", "Romantic", 1550);
b.printBook();
b.CalculateYearBook();
b.setAuthorBook("Pushkin");
b.setNameBook("Eugeny Onegin");
b.setJanreBook("Roman");
b.setYearBook(1834);
b.printBook();
b.CalculateYearBook();
{ // вариант 1
Book book_from_stream(cin);
book_from_stream.printBook();
}
{ // вариант 2
b = Book(cin);
b.printBook();
}
}