Новичков в C++ часто сбивает с толку тот факт, что константные функции-члены могут вызывать неконстантные методы для объектов, на которые ссылается класс (либо по указателю, либо по ссылке). Например, совершенно верно следующее:
class SomeClass
{
class SomeClassImpl;
SomeClassImpl * impl_; // PImpl idiom
public:
void const_method() const;
};
struct SomeClass::SomeClassImpl
{
void non_const_method() { /*modify data*/ }
};
void SomeClass::const_method() const
{
impl_->non_const_method(); //ok because impl_ is const, not *impl_
};
Однако иногда было бы довольно удобно, если бы константность распространялась на заостренные объекты (я добровольно использовал идиому PImpl, потому что это один из случаев, когда я думаю, что «распространение константности» было бы очень полезным).
При использовании указателей этого легко добиться, используя какой-нибудь интеллектуальный указатель с операторами, перегруженными константностью:
template < typename T >
class const_propagating_ptr
{
public:
const_propagating_ptr( T * ptr ) : ptr_( ptr ) {}
T & operator*() { return *ptr_; }
T const & operator*() const { return *ptr_; }
T * operator->() { return ptr_; }
T const * operator->() const { return ptr_; }
// assignment operator (?), get() method (?), reset() method (?)
// ...
private:
T * ptr_;
};
Теперь мне просто нужно изменить SomeClass::impl_
на const_propagating_ptr<SomeClassImpl>
, чтобы получить желаемое поведение.
Поэтому у меня есть несколько вопросов по этому поводу:
- Есть ли какие-то проблемы с распространением константности, которые я упустил из виду?
- Если нет, существуют ли какие-либо библиотеки, которые предоставляют классы для распространения константности?
- Разве не было бы полезно, чтобы общие интеллектуальные указатели (unique_ptr, shared_ptr и т. д.) предоставляли какое-то средство для получения такого поведения (например, через параметр шаблона)?
T const * const operator->() const { return ptr_; }
- наверное второйconst
здесь не нужен - person Andriy Tylychko   schedule 19.01.2011const_cast
избавиться от константности, она не не означает, что const бесполезен). Что касается второго комментария, вы правы, @robin, я по ошибке сделал это, чтобыptr_
не был... - person Luc Touraille   schedule 19.01.2011