Вызов неконстантного метода для члена из метода const
Я был удивлен, обнаружив эту "дыру" в "постоянстве":
#include <stdio.h>
class A
{
int r ;
public:
A():r(0){}
void nonconst()
{
puts( "I am in ur nonconst method" ) ;
r++;
}
} ;
class B
{
A a ;
A* aPtr ;
public:
B(){ aPtr = new A() ; }
void go() const
{
//a.nonconst() ; // illegal
aPtr->nonconst() ; //legal
}
} ;
int main()
{
B b ;
b.go() ;
}
Так в основном из const
метод B::go()
, вы можете вызвать неконстантную функцию - член (метко названную nonconst()
) если объект типа A
на него ссылается указатель.
Это почему? Похоже, проблема (вроде как было в моем коде, где я ее нашел).
3 ответа
Когда и объект типа B
является const, то все его члены являются const, что означает, что его два члена, в течение B::go()
эффективно
A const a;
A * const aPtr;
Первый постоянный объект типа A
, на котором вы можете вызывать только константные функции-члены. Второй, однако, является постоянным указателем на непостоянный A
, Вы не могли бы по закону сказать aPtr = <anything>
изнутри функции B::go()
, так как это изменило бы aPtr
, который является постоянным.
Указатель на константу A
будет объявлен как A const* aPtr
или же const A* aPtr
, который затем сделал бы вызов непостоянным A::nonconst()
незаконным.
"Константность" объекта не распространяется на другие объекты через указатели. В вашем примере const
часть либо весь объект a
или указатель aPtr
, Так как aPtr
это A *
и не const A *
Вы можете вызывать неконстантный метод.
Если вы измените
A* aPtr ;
в
const A* aPtr ;
тогда ты не сможешь позвонить aPtr->nonconst()
,
Определение языка const
Я был удивлен, обнаружив эту "дыру" в "постоянстве":
Здесь ничего нет.
const
применяется одинаково ко всем ученикам: в const
функция-член класса C
, this
имеет тип const C *
так что для члена C::mem
объявлен как тип T
:
class C {
// ...
T mem;
};
this->mem
имеет тип const T
,
Пожалуйста, возьмите тип, чтобы понять, что является объявленным типом T
и соответствующий const-квалифицированный тип для всех членов.
Похоже, проблема (вроде как было в моем коде, где я ее нашел).
То, что систематическое применение правил не дает ожидаемого результата, не означает, что есть проблема с правилами, это означает, что есть проблема с вашими ожиданиями.
Вы должны записать свои ожидания, чтобы увидеть, что вы ожидали неоднородного заявления, если const
для разных типов.
Когда вы программируете, вы должны логически рассуждать. Вы должны делать выводы, а не ожидать их, когда нет логической причины.
С помощью const
правильно
Это почему?
Ваши занятия называются A
а также B
Довольно трудно понять, что представляет собой логическое состояние, а что нет.;) Вы задаете "моральный" вопрос (не вопрос только о легальных / нелегальных программах на C++), а ваш фрагмент кода не имеет "морального" значения. Если вы действительно публикуете соответствующий код, мы можем сделать некоторые "моральные" суждения по этому поводу.
Логическое состояние
Вы должны объявить const
функции, которые не изменяют "логическое состояние" объекта, к которому он применяется.
Это означает, что вы должны определить, что такое "логическое состояние" экземпляров вашего класса: это абстрактное понятие, и только вы можете определить его, потому что это понятие высокого уровня. "Логическое состояние" относится к проблеме, которую должен решить ваш класс.
Затем вы можете определить, какие переменные влияют на логическое состояние: *(b.aPtr)
внести свой вклад в логическое состояние b
?
Тесно связанные вопросы
Вы знаете о конструкторе копирования?
Об операторе присвоения копии?
О деструкторе?