С++ для начинающих


         

Определение иерархии классов - часть 2


// не объектно-ориентированное решение

union op_type {

   // объединение не может содержать объекты классов с

   // ассоциированными конструкторами

   NotQuery *nq;

   OrQuery  *oq;

   AndQuery *aq;

   string   *word;

};

enum opTypes {

   Not_query=1, O_query, And_query, Name_query

};

class AndQuery {

public:

   // ...

private:

   /*

    * opTypes хранит информацию о фактических типах операндов запроса

    * op_type - это сами операнды

    */

    op_type _lop, _rop;

    opTypes _lop_type, _rop_type;

};

Хранить указатели на объекты можно и с помощью типа void*:

class AndQuery {

public:

   // ...

private:

    void * _lop, _rop;

    opTypes _lop_type, _rop_type;

};

Нам все равно нужен дискриминант, поскольку напрямую использовать объект, адресуемый указателем типа void*, нельзя, равно как невозможно определить тип такого объекта по указателю. (Мы не рекомендуем применять описанное решение в C++, хотя в языке C это весьма распространенный подход.)

Основной недостаток рассмотренных решений состоит в том, что ответственность за определение типа возлагается на программиста. Например, в случае решения, основанного на void*-указателях, операцию eval() для объекта AndQuery можно реализовать так:

void

AndQuery::

eval()

{

   // не объектно-ориентированный подход

   // ответственность за разрешение типа ложится на программиста

   // определить фактический тип левого операнда

   switch( _lop_type ) {

      case And_query:

           AndQuery *paq = static_cast<AndQuery*>(_lop);

           paq->eval();

           break;

      case Or_query:

           OrQuery *pqq = static_cast<OrQuery*>(_lop);

           poq->eval();

           break;

      case Not_query:

           NotQuery *pnotq = static_cast<NotQuery*>(_lop);

           pnotq->eval();

           break;

      case Name_query:

           AndQuery *pnmq = static_cast<NameQuery*>(_lop);

           pnmq->eval();

           break;




Содержание  Назад  Вперед