Тип этого * в С++
это может звучать глупо. В С++ prime 5th edition P258 говорится:
по умолчанию, тип этого является указателем константы для версии nonconst класса. Например, по умолчанию тип этого в функции члена Sales_data является Sales_data * const.
я могу понять, что для этого * является указателем const, который означает, что объект, который он указывает после инициализации, не может изменить. Но тогда он говорит:
хотя это неявно, оно следует за нормальными правилами инициализации, что означает, что (по умолчанию) мы не можем привязать это к объекту const.
но я написал следующие коды, он все еще был скомпонован:
class Test{
public:
Test() = default;
Test(const string &s): teststr(" ") {};
Test(int a) : testint(a) {};
Test(const string &s, int a): teststr(s), testint(a) {};
string getstr() const { return teststr; };
int getint() { return testint; }; //there is no const here
private:
string teststr;
int testint = 0;
};
int main(){
Test a("abc",2);
cout << a.getint() << " ";
cout << a.getstr() << endl;
cout << endl;
return 0;
}
поэтому мой вопрос:
если компилятор может скомпилировать его в порядке, есть ли "const" или нет, почему это имеет значение?
а затем в книге говорится:
в конце концов, тело isbn не изменяет объект, на который это указывает, поэтому наша функция будет более гибкой, если бы это был указатель на const.
и мне интересно, что такое гибкость? Не могли бы вы показать мне несколько примеров?
Ответы
Ответ 1
Для новичков this
часто отображается как постоянный указатель.
Однако this
на самом деле является значением prvalue (pure rvalue) типа указателя. Вы не можете назначить что-либо для значений основного типа, что подразумевает "константу" this
.
Точный тип this
зависит от cv-квалификации метода. Эмпирическое правило состоит в том, что cv-квалификация просто добавляется к обычному типу указателя - то есть, если метод Class
отмечен const
, тогда тип const
Class*
.
если компилятор может скомпилировать его в порядке, есть ли 'const' или не, почему это важно?
Если (и только если) тип pointee this
равен const
, вы не можете изменять членов класса.
Class const* ptr; // ptr->data is also const, not modifiable through this pointer
Class* ptr; // ptr->data isn't const - can be modified.
Методы const
-qualifier on позволяют различать методы для const
объектов и методов для non const
, что часто является необходимостью.
Ответ 2
В соответствии со стандартом С++ (9.3.2 Этот указатель)
1 В теле нестатической (9.3) функции-члена ключевое слово this является выражением prvalue, значением которого является адрес объекта для который вызывается функцией. Тип этого в членной функции класс X является X *. Если функция-член объявлена const, тип это const X *, если функция-член объявлена изменчивой, тип этого является изменчивым X *, и если объявлена функция-член const volatile, тип этого - const volatile X *.
Как вы видите, ничего не сказано, что this
имеет тип ClassTYpe * const
of ClassType const * const
. Это prvalue, которое не может быть изменено как любое prvalue, за исключением того, что для prvalue типа класса вы можете вызывать неконстантные функции-члены.
Как и для вас, вы смешиваете два типа указателя константы и указатель, указывающий на постоянную информацию.
Например, это объявление
const ClassType *p;
не объявляет постоянный указатель. Таким образом, сам указатель не может быть инициализирован. С другой стороны, декларация thsi
ClassTYpe * const p = new ClassTYpe;
объявляет константный указатель, и сам указатель инициализируется как любая другая константа.
Что касается этой цитаты из вашей книги
в конце концов, тело isbn не изменяет объект, к которому это точек, поэтому наша функция была бы более гибкой, если бы это был указатель к const
Тогда это означает, что было бы лучше определить функцию с квалификатором const. В этом случае его можно было бы вызвать для постоянных и непостоянных объектов. В противном случае он может быть вызван только для -не константных объектов, потому что внутри функции тип указателя this
не const ClassTYpe *
.
Ответ 3
"я могу понять, что для этого * является указателем const, который означает, что объект, который он указывает после инициализации, не может изменить. Но тогда он говорит:"
Нет, вы ошиблись. Будучи this
указателем const, вы не можете изменить значение указателя как
class MyClass {
void foo() {
MyClass a;
this = &a; // <<< Compiler error
}
}
Тип this
действительно отображается как
MyClass * const this;
и для const
экземпляров или ссылок
MyClass const * const this;
Обратите внимание, что это отличается от
const MyClass* some_const_instance_pointer;
Ответ 4
"Гибкость" заключается в том, что вы можете вызвать функцию const
на любом объекте, постоянном или нет. Вы не можете вызвать функцию const
для объекта const
(или ссылку/указатель на const
).
Таким образом, следующее:
const Test c;
cout << a.getint() << " "; // ERROR: non-const function
cout << a.getstr() << endl; // OK: const function
Как и эта гибкость, объявление функции-члена const
является хорошей идеей, поскольку это предотвратит случайную модификацию объекта в функции, которая не должна быть.
Ответ 5
Два ответа на два вопроса.
Указатель this
нельзя переназначить. В этом случае это означает const
. Вы можете изменить содержимое объекта, на который указывает this
, но вы не можете изменить, на какой объект он указывает.
Дополнительная гибкость при создании метода const
заключается в том, что он может использоваться как для объектов const
, так и для неконстантных объектов. Метод non-const не может использоваться для объекта const
.
Пример:
class A {
int a;
public:
int method() const {
return a;
}
};
void f() {
A a;
const A ca;
a.method();
ca.method();
}