в C ++ prime 5th edition P258 это может звучать глупо:
по умолчанию типом этого является константный указатель на неконстантную версию класса type. Например, по умолчанию типом этого в функции-члене 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.
и мне интересно, что такое гибкость? Не могли бы вы показать мне несколько примеров?
Для начинающих, this
часто изображается как постоянный указатель.
Тем не мение, this
на самом деле является prvalue (чисто 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
-квалификатор по методам позволяет различать методы для const
объекты и методы дляconst
те, которые часто являются необходимостью.
Согласно стандарту C ++ (9.3.2. Указатель this)
1 В теле нестатической (9.3) функции-члена ключевое слово this
является выражением prvalue, значением которого является адрес объекта для
которую функция называется. Тип этого в функции-члене
класс X — это X *. Если функция-член объявлена как const, тип
это const X *, если функция-член объявлена как volatile,
тип этого является изменчивым X *, и если функция-член объявлена
const volatile, тип этого const volatile X *.
Как видите, ничего не сказано, что this
имеет тип ClassTYpe * const
из ClassType const * const
, Это prvalue, которое нельзя изменить как любое значение prvalue, за исключением того, что для prvalue типа класса вы можете вызывать неконстантные функции-члены.
Что касается вас, то вы смешиваете два типа постоянный указатель и указатель, который указывает на постоянные данные.
Например, это объявление
const ClassType *p;
не объявляет постоянный указатель. Таким образом, сам указатель может быть не инициализирован. С другой стороны, эта декларация
ClassTYpe * const p = new ClassTYpe;
объявляет постоянный указатель и сам указатель должен быть инициализирован как любая другая константа.
Что касается этой цитаты из вашей книги
в конце концов, тело isbn не меняет объект, к которому это
точки, поэтому наша функция была бы более гибкой, если бы это был указатель
const
Тогда это означает, что было бы лучше определить функцию с квалификатором const. В этом случае он может быть вызван для постоянных и непостоянных объектов. В противном случае он может быть вызван только для неконстантных объектов, потому что внутри функции указатель типа this
не является const ClassTYpe *
,
«Гибкость» заключается в том, что вы можете назвать const
функция на любой объект, постоянный или нет. Вы не можете позвонить неconst
функция на const
объект (или ссылка / указатель на const
).
Так что следующее не получится:
const Test c;
cout << a.getint() << " "; // ERROR: non-const function
cout << a.getstr() << endl; // OK: const function
Как и эта гибкость, объявление функции-члена const
это хорошая идея, так как это предотвратит случайное изменение объекта в функции, которая не должна.
«Я могу понять, что для этого * указатель const означает, что объект, на который он указывает после инициализации, не может быть изменен. Но тогда он говорит:»
Нет, вы ошиблись. бытие this
константный указатель означает, что вы не можете изменить значение указателя как
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;
Два вопроса, два ответа.
this
указатель не может быть переназначен. Вот что подразумевается под const
в этом случае. Вы можете изменить содержимое объекта, который this
указывает на, но вы не можете изменить, на какой объект он указывает.
Дополнительная гибкость создания метода const
является то, что он может быть использован на обоих const
и неконстантные объекты. Неконстантный метод не может использоваться на const
объект.
Пример:
class A {
int a;
public:
int method() const {
return a;
}
};
void f() {
A a;
const A ca;
a.method();
ca.method();
}