Для чего * вы * используете конструкторы C ++ ABC? - PullRequest
1 голос
/ 17 января 2009

Для чего здесь люди используют конструкторы C ++ Abstract Base Class в поле? Я говорю о чистых интерфейсных классах, не имеющих данных и не чистых виртуальных членов.

Может кто-нибудь продемонстрировать идиомы, которые используют конструкторы ABC полезным способом? Или это просто присуще природе использования ABC для реализации интерфейсов, что они остаются пустыми, встроенными и защищенными?

Ответы [ 6 ]

5 голосов
/ 17 января 2009

Может кто-нибудь продемонстрировать идиомы, которые используют конструкторы ABC полезным способом?

Вот пример, хотя это надуманный, необычный пример.

Вы можете использовать его для хранения списка всех экземпляров:

class IFoo
{
private:
  //static members to keep a list of all constructed instances
  typedef std::set<IFoo*> Set;
  static Set s_set;

protected:
  //new instance being created
  IFoo()
  {
    s_set.insert(this);
  }

public:
  //instance being destroyed
  virtual ~IFoo()
  {
    s_set.remove(this);
  }

  ... plus some other static method and/or property
      which accesses the set of all instances ...
};

Или это просто присуще природе использования ABC для реализации интерфейсов, что они остаются пустыми, встроенными и защищенными?

Чаще всего они просто не заявлены вообще! Нет причин объявлять их:

  • Пустой и встроенный => зачем объявлять об этом?
  • Protected => ABC, вероятно, уже имеет некоторые чистые виртуальные методы и, следовательно, уже не может быть создан, кроме как подкласс.
3 голосов
/ 17 января 2009

Предположим, что существует некоторое поведение, общее для всех производных классов. Например, регистрация в каком-либо внешнем реестре или проверка действительности чего-либо.

Весь этот общий код может быть помещен в конструктор базового класса, и он будет вызываться неявно из конструкторов каждого из производных классов.

1 голос
/ 17 января 2009

Я не могу придумать много полезных примеров. Класс без данных-членов не имеет состояния и поэтому не может ничего инициализировать. Вы можете сделать так, чтобы конструктор / деструктор занялся ведением журнала для вас. Например, чтобы зарегистрировать создание / уничтожение всех объектов Visitor:

class Visitor {
public:
    Visitor() {
        std::cout << "Visitor@" << this << " created" 
                  << std::endl;
    }

    virtual ~Visitor() {
        std::cout << "Visitor@" << this << " destroyed" 
                  << std::endl;
    }

    virtual void visitA(A*) = 0;
    virtual void visitB(B*) = 0;
    // ...
};
1 голос
/ 17 января 2009

Помните: "Получение ресурсов - это инициализация" .

Иногда мы используем абстрактные базовые классы в качестве механизма блокировки. Например, в многопоточной среде, где несколько потоков должны совместно использовать один ресурс, поток может использовать конструктор для получения ресурса, а деструктор - для освобождения ресурса

void PlayWithPaintBallGun(Target &target)
{
    PaintBallGun paintBallGun;    // constructor waits until the gun is free,
                                  // then picks it up.

    paintBallGun.Aim(target);     // Shoot something
    paintBallGun.Fire();          //

                                  // Clever! The destructor is automatically
                                  // called when it goes out of scope. So we
                                  // can't forget to put the gun down.
}

Hugo

1 голос
/ 17 января 2009

Как можно использовать конструктор абстрактного базового класса для чего-либо?

Предположим, у вас есть абстрактный базовый класс B и производный класс D. Когда создается объект типа D, сначала вызывается конструктор B, но в этот момент объект "is" по-прежнему имеет тип B (см. here ) - в частности, вызов любых виртуальных функций из тела конструктора B вызовет собственных реализаций B этих функций. Но если B является чисто абстрактным классом, ни одна из этих виртуальных функций не определена, поэтому программа немедленно завершит работу.

Я предполагаю, что вы хотели, чтобы конструктор B вызывал реализацию виртуальной функции самого производного класса (например, D), верно? В целом это было бы плохой идеей, поскольку объект D еще не полностью сконструирован, поэтому любой доступ к переменным-членам в D изнутри реализации виртуальной функции D мог бы получить доступ к неинициализированной памяти.

0 голосов
/ 17 января 2009

обычно его инициализируют только члены с разумными значениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...