Если вы действительно хотите иметь тот же класс (при условии, что семантика все еще имеет смысл), то я думаю, что вы хотите что-то вроде:
const Cfoo f1( 5 );
const CfooHolder h1( f1 );
Cfoo f2( 0 );
CfooHolder h2( f2 );
Я думаю, что вы надеетесь, что C ++ сделаетследующие решения: a) Обрабатывать объект Cfoo как const
, если он был const
, или неконстантным, если он был неконстантным.Ключом является как определение Cfoo , так и определение CfooHolder .Если Cfoo равен const
, тогда CfooHolder должен быть объявлен const
, иначе он не сможет скомпилироваться.Если Cfoo не является константой, то вы можете создать CfooHolder , которые могут быть как const
, так и не- const
.б) метод SetI()
должен перестать компилироваться при использовании в const CfooHolder объекте.В приведенном выше примере h1.SetI( 6 );
не должен компилироваться.
Мой ответ таков: если a) сработало, то b) также сработает автоматически.Проблема заключается в достижении а), что, насколько я знаю, невозможно.
Чтобы это работало, атрибут должен быть сделан const
или неконстантным в зависимости от объекта его класса.постоянный или неконстантный.Хотя объект класса может изменить это «состояние», атрибуты остаются неизменными.Но вы можете использовать методы const
только тогда, когда объект этого класса равен const
(например, когда параметр передается по постоянной ссылке).Таким образом, C ++ не будет поддерживать это, потому что он не работает таким образом.
Другой возможностью было бы позволить самому атрибуту быть константным и неконстантным одновременно, что не имеет смысла.
Краткий ответ: это невозможно, и будет повторение кода.Если вы действительно хотите избежать этого, а обертка достаточно сложна, чтобы беспокоиться, единственный способ - создать общий держатель, а затем постоянные и непостоянные обертки вокруг общего держателя, избегая повторения до минимума.
class CfooHolder
{
public:
explicit CfooHolder(Cfoo& foo):foo_(foo){};
int GetI()const{ return( foo_.GetI() ); }
virtual void SetI(int i){ foo_.SetI(i); }
protected:
Cfoo& foo_;
};
class CfooHolderNonConst : public CfooHolder {
public:
explicit CfooHolderNonConst(Cfoo& foo):CfooHolder(foo){};
};
class CfooHolderConst: public CfooHolder
{
public:
explicit CfooHolderConst(const Cfoo& foo):CfooHolder(const_cast<Cfoo &>( foo )){}
void SetI(int i){ throw std::runtime_error( "Don't write to me!" ); }
};
Он не идеален, но работает на заявленных условиях.Метод SetI()
выдаст ошибку времени выполнения, но если объект CfooHolderConst объявлен как const
, то вызов SetI()
даже не скомпилируется.
Надеюсь, этопомогает.