C ++ метод получения констант с отложенной инициализацией

Вы можете использовать

System.getProperty("line.separator");

, чтобы получить разделитель строк

30
задан Dave Mateer 30 July 2010 в 19:30
поделиться

6 ответов

Я предлагаю инкапсулировать ответ Джеймса Каррана в отдельный класс, если вы делаете это часто:

template <typename T>
class suspension{
   std::tr1::function<T()> initializer;
   mutable T value;
   mutable bool initialized;
public:
   suspension(std::tr1::function<T()> init):
      initializer(init),initialized(false){}
   operator T const &() const{
      return get();
   }
   T const & get() const{
      if (!initialized){
         value=initializer();
         initialized=true;
      }
      return value;
   }
};

Теперь используйте это в своем коде следующим образом:

class MyClass {
  MyClass() : expensive_object_(CreateExpensiveObject) {}
  QObject* GetExpensiveObject() const {
    return expensive_object_.get();
  }
private:
  suspension<QObject *> expensive_object_;
};
19
ответ дан 27 November 2019 в 23:53
поделиться

Ваш метод получения на самом деле не является константой, поскольку он меняет содержимое объекта. Я думаю, ты слишком долго об этом думаешь.

-1
ответ дан 27 November 2019 в 23:53
поделиться

Это нормально и является типичным способом сделать это.

Вам придется объявить expensive_object_ как mutable

mutable QObject *expensive_object_; 

mutable в основном означает "Я знаю, что нахожусь в const-объекте, но модификация этого не нарушит const-ness."

.
23
ответ дан 27 November 2019 в 23:53
поделиться

Сделать expensive_object_ mutable.

6
ответ дан 27 November 2019 в 23:53
поделиться

Используйте const_cast для обхода константы в одном конкретном месте.

QObject* GetExpensiveObject() const {
  if (!expensive_object_) {
    const_cast<QObject *>(expensive_object_) = CreateExpensiveObject();
  }
  return expensive_object_;
}

IMHO, это лучше, чем сделать Road_object_ изменяемым , потому что вы не теряете константную безопасность во всех других ваших методах.

4
ответ дан 27 November 2019 в 23:53
поделиться

Рассматривали ли вы класс-оболочку? Возможно, вам удастся обойтись чем-то вроде умного указателя, только с возвращающими константу версиями operator * и operator -> и, возможно, operator [] ... Вы можете получить поведение, подобное scoped_ptr , в качестве бонуса.

Давайте попробуем, я уверен, что люди могут указать на несколько недостатков:

template <typename T>
class deferred_create_ptr : boost::noncopyable {
private:
    mutable T * m_pThing;
    inline void createThingIfNeeded() const { if ( !m_pThing ) m_pThing = new T; }
public:
    inline deferred_create_ptr() : m_pThing( NULL ) {}
    inline ~deferred_create_ptr() { delete m_pThing; }

    inline T * get() const { createThingIfNeeded(); return m_pThing; }

    inline T & operator*() const { return *get(); }
    inline T * operator->() const { return get(); }

    // is this a good idea?  unintended conversions?
    inline T * operator T *() const { return get(); }
};

Использование type_traits могло бы улучшить ситуацию ...

Вам потребуются разные версии для указатели на массивы, и вам, возможно, придется немного поиграться с функтором-создателем или фабричным объектом или чем-то еще, если вы хотите передать аргументы конструктору T .

Но вы могли бы использовать это так:

class MyClass {
public:
    // don't need a constructor anymore, it comes up NULL automatically
    QObject * getExpensiveObject() const { return expensive_object_; }

protected:
    deferred_create_ptr<QObject> expensive_object_;
};

Пора начать, скомпилировать это и посмотреть, смогу ли я его сломать ... =)

3
ответ дан 27 November 2019 в 23:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: