Новичков в 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
для получения желаемого поведения.
Итак, у меня есть несколько вопросов по этому поводу: