Читаем Thinking In C++. Volume 2: Practical Programming полностью

#include

using std::string;

using std::ostream;

using std::cout;


// The following have underscores because

// they are macros. For consistency,

// succeed_() also has an underscore.


#define test_(cond) \

  do_test(cond, #cond, __FILE__, __LINE__)

#define fail_(str) \

  do_fail(str, __FILE__, __LINE__)


namespace TestSuite {


class Test {

public:

  Test(ostream* osptr = &cout);

  virtual ~Test(){}

  virtual void run() = 0;

  long getNumPassed() const;

  long getNumFailed() const;

  const ostream* getStream() const;

  void setStream(ostream* osptr);

  void succeed_();

  long report() const;

  virtual void reset();

protected:

  void do_test(bool cond, const string& lbl,

    const char* fname, long lineno);

  void do_fail(const string& lbl,

    const char* fname, long lineno);

private:

  ostream* osptr;

  long nPass;

  long nFail;

  // Disallowed:

  Test(const Test&);

  Test& operator=(const Test&);

};


inline Test::Test(ostream* osptr) {

  this->osptr = osptr;

  nPass = nFail = 0;

}


inline long Test::getNumPassed() const {

  return nPass;

}


inline long Test::getNumFailed() const {

  return nFail;

}


inline const ostream* Test::getStream() const {

  return osptr;

}


inline void Test::setStream(ostream* osptr) {

  this->osptr = osptr;

}


inline void Test::succeed_() {

  ++nPass;

}


inline void Test::reset() {

  nPass = nFail = 0;

}


} // namespace TestSuite

#endif // TEST_H ///:~


There are three virtual functions in the Test class:

·         A virtual destructor

·         The function reset( )

·         The pure virtual function run( )

As explained in Volume 1, it is an error to delete a derived heap object through a base pointer unless the base class has a virtual destructor. Any class intended to be a base class (usually evidenced by the presence of at least one other virtual function) should have a virtual destructor. The default implementation of the Test::reset( ) resets the success and failure counters to zero. You might want to override this function to reset the state of the data in your derived test object; just be sure to call Test::reset( ) explicitly in your override so that the counters are reset. The Test::run( ) member function is pure virtual, of course, since you are required to override it in your derived class.

The test_( ) and fail_( ) macros can include file name and line number information available from the preprocessor. We originally omitted the trailing underscores in the names, but the original fail( ) macro collided with ios::fail( ), causing all kinds of compiler errors.

Here is the implementation of Test:

//: TestSuite:Test.cpp {O}

#include "Test.h"

#include

#include   // Note: Visual C++ requires /GR

using namespace std;

using namespace TestSuite;


void Test::do_test(bool cond,

  const std::string& lbl, const char* fname,

  long lineno) {

  if (!cond)

    do_fail(lbl, fname, lineno);

  else

    succeed_();

}


void Test::do_fail(const std::string& lbl,

  const char* fname, long lineno) {

  ++nFail;

  if (osptr) {

    *osptr << typeid(*this).name()

           << "failure: (" << lbl << ") , "

           << fname

           << " (line " << lineno << ")\n";

  }

}


long Test::report() const {

  if (osptr) {

    *osptr << "Test \"" << typeid(*this).name()

           << "\":\n\tPassed: " << nPass

           << "\tFailed: " << nFail

           << endl;

  }

  return nFail;

} ///:~


No rocket science here. The Test class just keeps track of the number of successes and failures as well as the stream where you want Test::report( ) to display the results. The test_( ) and fail_( ) macros extract the current file name and line number information from the preprocessor and pass the file name to do_test( ) and the line number to do_fail( ), which do the actual work of displaying a message and updating the appropriate counter. We can’t think of a good reason to allow copy and assignment of test objects, so we have disallowed these operations by making their prototypes private and omitting their respective function bodies.

Here is the header file for Suite:.

//: TestSuite:Suite.h

#ifndef SUITE_H

#define SUITE_H

#include "../TestSuite/Test.h"

#include

#include

using std::vector;

using std::logic_error;


namespace TestSuite {


class TestSuiteError : public logic_error {

public:

  TestSuiteError(const string& s = "")

    : logic_error(s) {}

};


class Suite {

public:

  Suite(const string& name, ostream* osptr = &cout);

  string getName() const;

  long getNumPassed() const;

  long getNumFailed() const;

  const ostream* getStream() const;

  void setStream(ostream* osptr);

  void addTest(Test* t) throw (TestSuiteError);

  void addSuite(const Suite&);

  void run();  // Calls Test::run() repeatedly

  long report() const;

  void free();  // Deletes tests

private:

  string name;

  ostream* osptr;

  vector tests;

  void reset();

  // Disallowed ops:

  Suite(const Suite&);

  Suite& operator=(const Suite&);

};


inline

Suite::Suite(const string& name, ostream* osptr)

   : name(name) {

  this->osptr = osptr;

}


inline string Suite::getName() const {

  return name;

}


inline const ostream* Suite::getStream() const {

  return osptr;

}


inline void Suite::setStream(ostream* osptr) {

  this->osptr = osptr;

}


} // namespace TestSuite

Перейти на страницу:

Похожие книги

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

Программирование, программы, базы данных / Программное обеспечение / Книги по IT