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

void testPrintable(const Printable& p) {

  p.print(cout);

  cout << endl;

}

template

void testIntable(const Intable& n) {

  int i = n.toInt() + 1;

  cout << i << endl;

}

template

void testStringable(const Stringable& s) {

  string buf = s.toString() + "th";

  cout << buf << endl;

}

int main() {

  Able a(7);

  testPrintable(a);

  testIntable(a);

  testStringable(a);

} ///:~

The names Printable, Intable, and Stringable are now just template parameters that assume the existence of the operations indicated in their respective contexts. Some people are more comfortable with the first version, because the type names guarantee by inheritance that the expected interfaces are implemented. Others are content with the fact that if the operations required by the test functions are not satisfied by their template type arguments, the error is still caught at compile time. The latter approach is technically a "weaker" form of type checking than the former (inheritance) approach, but the effect on the programmer (and the program) is the same. This is one form of weak typing that is acceptable to many of today’s C++ programmers.

<p>Implementation inheritance</p>

As we stated earlier, C++ provides only implementation inheritance, meaning that you inherit everything from all your base classes. This can be a good thing, of course, because it frees you from having to implement everything in the derived class, as we had to do with the interface inheritance examples earlier. A common use of multiple inheritance involves using mixin classes, which are classes not intended to be instantiated independently, but exist to add capabilities to other classes through inheritance.

As an example, suppose we are clients of a class that supports access to a database. We will likely only have a header file available (which is part of the point we are about to make), but for illustration, assume the following, simple implementation of a Database class:

//: C09:Database.h

// A prototypical resource class

#ifndef DATABASE_H

#define DATABASE_H

#include

#include

#include

using std::cout;

using std::string;

using std::runtime_error;

struct DatabaseError : runtime_error {

  DatabaseError(const string& msg) : runtime_error(msg)

  {}

};

class Database {

public:

  Database(const string& dbStr) : dbid(dbStr) {}

  virtual ~Database(){}

  void open() throw(DatabaseError) {

    cout << "connected to " << dbid << '\n';

  }

  void close() {

    cout << dbid << " closed\n";

  }

  //Other database functions...

private:

  string dbid;

};

#endif ///:~

We’re leaving out actual database functionality (storing, retrieving, and so on), but that’s actually not important here. Using this class requires a database connection string and that you call Database::open( ) to connect and Database::close( ) to disconnect:

//: C09:UseDatabase.cpp

#include "Database.h"

int main() {

  Database db("MyDatabase");

  db.open();

  // Use other db functions...

  db.close();

}

/* Output:

connected to MyDatabase

MyDatabase closed

*/ ///:~

In a typical client-server situation, a client will have multiple objects sharing a connection to a database. It is important that the database eventually be closed, but only after access to it is no longer required. It is common to encapsulate this behavior through a class that tracks the number of client entities using the database connection and to automatically terminate the connection when that count goes to zero. To add reference counting to the Database class, we create a mixin class named Countable and mix it into the Database class by creating a new class, DBConnection, through multiple inheritance. Here’s the Countable mixin class:

//: C09:Countable.h

// A "mixin" class

#ifndef COUNTABLE_H

#define COUNTABLE_H

#include

class Countable {

public:

  long attach() { return ++count; }

  long detach() {

    return (--count > 0) ? count : (delete this, 0);

  }

  long refCount() const { return count; }

protected:

  Countable() { count = 0; }

  virtual ~Countable() { assert(count == 0); }

private:

  long count;

};

#endif ///:~

It is evident that this is not a standalone class because its constructor is protected; it therefore requires a friend or a derived class to use it. It is important that the destructor is virtual, of course, because it is called only from the delete this statement in detach( ), and we of course want derived objects to be completely destroyed.[107] The DBConnection class derives from both Database and Countable and provides a static create( ) function that initializes its Countable subobject. (This is an example of the Factory Method design pattern, discussed in the next chapter.)

//: C09:DBConnection.h

// Uses a "mixin" class

#ifndef DBCONNECTION_H

#define DBCONNECTION_H

#include "Countable.h"

#include "Database.h"

#include

#include

using std::string;

class DBConnection : public Database, public Countable {

public:

  static DBConnection* create(const string& dbStr)

  throw(DatabaseError) {

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

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

3ds Max 2008
3ds Max 2008

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

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

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