абстрактный класс и статические методы - PullRequest
2 голосов
/ 21 июля 2011

У меня есть абстрактный класс:

class A
{
  public:
  bool loaded_;
  virtual int load() = 0;
}

И несколько производных классов:

class B:public A
{
  public:
  int load();
  static B& instance();
}  

class C:public A
{
  public:
  int load();
  static C& instance();
}  

Дело в том, что код внутри методов :: instance () одинаков для каждого класса:

static B& B::instance()
{
  static B instance_;
  if (!instance_.loaded_)
  {
    instance_.load();
    instance_.loaded_=true;
  }
  return instance_;
}

static C& C::instance()
{
  static C instance_;
  if (!instance_.loaded_)
  {
    instance_.load();
    instance_.loaded_=true;
  }
  return instance_;
}

Я хотел бы разложить этот метод :: instance, но, учитывая, что он использует виртуальный метод :: load, я не могу определить его в классе A. Теоретически, я знаю, что это странно, так как класс A должен иметь 0 экземпляров, а B, C должен иметь 1 экземпляр, но также имеет смысл, что этот код должен быть разложен.

Как бы вы решили эту проблему?

Ответы [ 2 ]

8 голосов
/ 21 июля 2011

Вы можете сделать instance() бесплатным шаблоном функции:

template<class T>
T& instance()
{
  static T instance_;
  if (!instance_.loaded_)
  {
    instance_.load();
    instance_.loaded_=true;
  }
  return instance_;
}

Тогда вы можете использовать это так:

instance<B>().do_stuff()
3 голосов
/ 21 июля 2011

Это обычное использование CRTP, определите функцию, которая создает экземпляр в шаблоне, а затем создайте его экземпляр в каждом типе:

struct A {
   virtual ~A() {}     // don't forget to make your destructor virtual!
   virtual void load() = 0;
};
template <typename T>
struct instance_provider {
    static T& instance() { /* implementation */ }
};
struct B : A, instance_provider<B> {
   virtual void load();
};
struct C : A, instance_provider<C> {
   virtual void load();
};
...