Вы можете использовать
System.getProperty("line.separator");
, чтобы получить разделитель строк
Я предлагаю инкапсулировать ответ Джеймса Каррана в отдельный класс, если вы делаете это часто:
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_;
};
Ваш метод получения на самом деле не является константой, поскольку он меняет содержимое объекта. Я думаю, ты слишком долго об этом думаешь.
Это нормально и является типичным способом сделать это.
Вам придется объявить expensive_object_
как mutable
mutable QObject *expensive_object_;
mutable
в основном означает "Я знаю, что нахожусь в const-объекте, но модификация этого не нарушит const-ness."
Используйте const_cast
для обхода константы в одном конкретном месте.
QObject* GetExpensiveObject() const {
if (!expensive_object_) {
const_cast<QObject *>(expensive_object_) = CreateExpensiveObject();
}
return expensive_object_;
}
IMHO, это лучше, чем сделать Road_object_
изменяемым
, потому что вы не теряете константную безопасность во всех других ваших методах.
Рассматривали ли вы класс-оболочку? Возможно, вам удастся обойтись чем-то вроде умного указателя, только с возвращающими константу версиями 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_;
};
Пора начать, скомпилировать это и посмотреть, смогу ли я его сломать ... =)