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

#endif // SUITE_H ///:~


The Suite class holds pointers to its Test objects in a vector. Notice the exception specification on the addTest( ) member function. When you add a test to a suite, Suite::addTest( ) verifies that the pointer you pass is not null; if it is null, it throws a TestSuiteError exception. Since this makes it impossible to add a null pointer to a suite, addSuite( ) asserts this condition on each of its tests, as do the other functions that traverse the vector of tests (see the following implementation). Copy and assignment are disallowed as they are in the Test class.

//: TestSuite:Suite.cpp {O}

#include "Suite.h"

#include

#include

using namespace std;

using namespace TestSuite;


void Suite::addTest(Test* t) throw(TestSuiteError) {

  // Verify test is valid and has a stream:

  if (t == 0)

    throw TestSuiteError(

      "Null test in Suite::addTest");

  else if (osptr && !t->getStream())

    t->setStream(osptr);

  tests.push_back(t);

  t->reset();

}


void Suite::addSuite(const Suite& s) {

for (size_t i = 0; i < s.tests.size(); ++i) {

  assert(tests[i]);

addTest(s.tests[i]);

  }

}


void Suite::free() {

  for (size_t i = 0; i < tests.size(); ++i) {

    delete tests[i];

    tests[i] = 0;

  }

}


void Suite::run() {

  reset();

  for (size_t i = 0; i < tests.size(); ++i) {

    assert(tests[i]);

    tests[i]->run();

  }

}


long Suite::report() const {

  if (osptr) {

    long totFail = 0;

    *osptr << "Suite \"" << name

             << "\"\n=======";

    size_t i;

    for (i = 0; i < name.size(); ++i)

      *osptr << '=';

    *osptr << "=\n";

    for (i = 0; i < tests.size(); ++i) {

      assert(tests[i]);

      totFail += tests[i]->report();

    }

    *osptr << "=======";

    for (i = 0; i < name.size(); ++i)

      *osptr << '=';

    *osptr << "=\n";

    return totFail;

  }

  else

    return getNumFailed();

}


long Suite::getNumPassed() const {

  long totPass = 0;

  for (size_t i = 0; i < tests.size(); ++i) {

    assert(tests[i]);

    totPass += tests[i]->getNumPassed();

  }

  return totPass;

}


long Suite::getNumFailed() const {

  long totFail = 0;

  for (size_t i = 0; i < tests.size(); ++i) {

    assert(tests[i]);

    totFail += tests[i]->getNumFailed();

  }

  return totFail;

}


void Suite::reset() {

  for (size_t i = 0; i < tests.size(); ++i) {

    assert(tests[i]);

    tests[i]->reset();

  }

} ///:~


We will be using the TestSuite framework wherever it applies throughout the rest of this book.

Debugging techniques

The best debugging habit to get into is to use assertions as explained in the beginning of this chapter; by doing so you’ll be more likely to find logic errors before they cause real trouble. This section contains some other tips and techniques that might help during debugging.

Trace macros

Sometimes it’s helpful to print the code of each statement as it is executed, either to cout or to a trace file. Here’s a preprocessor macro to accomplish this:.

#define TRACE(ARG) cout << #ARG << endl; ARG


Now you can go through and surround the statements you trace with this macro. Of course, it can introduce problems. For example, if you take the statement:.

for(int i = 0; i < 100; i++)

  cout << i << endl;


and put both lines inside TRACE( ) macros, you get this:

TRACE(for(int i = 0; i < 100; i++))

TRACE(  cout << i << endl;)


which expands to this:

cout << "for(int i = 0; i < 100; i++)" << endl;

for(int i = 0; i < 100; i++)

  cout << "cout << i << endl;" << endl;

cout << i << endl;


which isn’t exactly what you want. Thus, you must use this technique carefully.

The following is a variation on the TRACE( ) macro:

#define D(a) cout << #a "=[" << a << "]" << '\n';


If you want to display an expression, you simply put it inside a call to D( ). The expression is displayed, followed by its value (assuming there’s an overloaded operator << for the result type). For example, you can say D(a + b). Thus, you can use this macro any time you want to test an intermediate value to make sure things are okay.

Of course, these two macros are actually just the two most fundamental things you do with a debugger: trace through the code execution and display values. A good debugger is an excellent productivity tool, but sometimes debuggers are not available, or it’s not convenient to use them. These techniques always work, regardless of the situation.

Trace file

DISCLAIMER: This section and the next contain code which is officially unsanctioned by the C++ standard. In particular, we redefine cout and new via macros, which can cause surprising results if you’re not careful. Our examples work on all the compilers we use, however, and provide useful information. This is the only place in this book where we will depart from the sanctity of standard-compliant coding practice. Use at your own risk!

The following code allows you to easily create a trace file and send all the output that would normally go to cout into the file. All you have to do is #define TRACEON and include the header file (of course, it’s fairly easy just to write the two key lines right into your file):.

//: C03:Trace.h

// Creating a trace file

#ifndef TRACE_H

#define TRACE_H

#include


#ifdef TRACEON

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

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

3ds Max 2008
3ds Max 2008

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

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

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