#include <iostream>
class Hello {
public:
void Test() {
std::cout << "Testing" << std::endl;
}
};
class Hi {
public:
Hi()
:hello(new Hello())
{}
~Hi()
{
delete hello;
}
void Testing() const {
hello->Test();
}
private:
Hello * hello;
};
int main(int argc, char ** argv) {
Hi hi; ;
hi.Testing();
return 0;
}
Как я знаю, непостоянная функция-член не может быть вызвана внутри постоянной функции-члена, но как приведенный выше код был успешно скомпилирован и дает ожидаемый результат.
внутри Hi::Testing
, hi
объект «является постоянным». Что означает указатель hello
не может быть изменено внутри этого метода. (Это как будто hello
был определен как Hello * const hello;
на время этого метода.)
Но это не значит, что hello
превращается в указатель на const (который будет выглядеть Hello const * const hello;
). Объект, на который указывает hello
не const, так что вы можете вызывать его неконстантные методы без ограничений.
Вы можете свести проблему к следующей ситуации:
Foo x;
Foo * p1 = &x;
Foo * const p2 = &x;
p1->non_const_method(); // OK
p2->non_const_method(); // OK
Foo const * q1 = &x;
Foo const * const q2 = &x;
q1->non_const_method(); // error
q2->non_const_method(); // error
Будь или не твой Hi
-объект постоянно влияет только на верхний уровень const
модификатор в этой аналогии (т.е. Hi::hello
является Hello *
или же Hello * const
). Тем не менее первый Модификатор const является неотъемлемой частью самого типа указателя (и не зависит от константности вашего объекта).
Если у вас есть указатель на объект const, это ограничит вас вызовом функций-членов const в целевом объекте.
Постоянный указатель на (нормальный) объект просто означает, что вы не можете изменить сам указатель. Поскольку это по-прежнему указатель на обычный объект, вы можете использовать любую функцию-член, а не только константные функции-члены. Если целевой объект имеет постоянные и нормальные перегрузки этой функции, будет выбрана нормальная перегрузка.
Когда у вас есть указатель в качестве члена const-объекта, вы получаете второй, а не первый.