Как "const" отличается на C и С++?
Как стандартная квалификация по переменным отличается на C и С++?
from: Имеет ли "const" просто означает только для чтения или что-то еще?
"Что вызвало этот вопрос, был этот ответ: qaru.site/info/65307/..., где он утверждает, что const" just "означает" только для чтения "на C. Я думал, что все const означает, независимо от того, был ли он C или С++. Что он имеет в виду?"
Ответы
Ответ 1
const
в C нельзя использовать для создания постоянных выражений.
Например:
#include <stdio.h>
int main()
{
int i = 2;
const int C = 2;
switch(i)
{
case C : printf("Hello") ;
break;
default : printf("World");
}
}
не работает в C, потому что метка case не сводится к целочисленной константе.
Ответ 2
const
означает, что вы обещаете не изменять эту переменную. Он все еще может быть изменен.
class A {
public:
A(const int& a);
int getValue() const;
void setValue(int b);
private:
const int& a;
};
A::A(a) : a(a) {}
int A::getValue() const {
return a;
}
void A::setValue(int b) {
a = b; // error
}
int main() {
int my_a = 0;
A a(my_a);
std::cout << a.getValue() << std::endl; // prints 0
my_a = 42;
std::cout << a.getValue() << std::endl; // prints 42
}
Без метода A::*
может измениться a
, но main
может. Это очень похоже на C и С++.
У С++ есть несколько (ограниченных) способов обойти const
, которые должны препятствовать неправильному отбрасыванию const
программистам.
Возьмите класс, подобный этому.
class A {
public:
A();
int getValue();
private:
static int expensiveComputation();
int cachedComputation;
};
A::A() : cachedComputation(0) {}
A::getValue() {
if (cachedComputation == 0)
cachedComputation = expensiveComputation();
return cachedComputation;
}
cachedComputation
неявно означает this->cachedComputation
. Помните об этом.
int main() {
A a1;
const A a2;
std::cout << a1.getValue() << std::endl;
std::cout << a2.getValue() << std::endl; // error
}
a2.getValue()
является незаконным, так как на const A a2
вызывается метод не const
. Можно отбросить const
-ness...
std::cout << ((A&)a2).getValue() << std::endl; // C-style cast
std::cout << const_cast<A&>(a2).getValue() << std::endl; // C++-style cast
Второй предпочтительнее, потому что компилятор проверяет, что только const
-ness ливается, ничего больше. Однако это все еще не идеально. Вместо этого в класс должен быть добавлен новый метод.
class A {
public:
int getValue() const;
};
A::getValue() const {
if (cachedComputation == 0)
cachedComputation = expensiveComputation(); // error
return cachedComputation;
}
Теперь существует метод const
, поэтому a2.getValue()
в порядке. Однако конечный const
означает, что методу присваивается указатель const A *this
, а не указатель A *this
, как обычно, что делает this->cachedComputation
a const int &
, который не может быть мутирован.
const_cast
может быть применен внутри метода, но лучше было бы изменить это одно членное объявление.
class A {
private:
mutable int cachedComputation;
};
Теперь даже с const A *this
, this->cachedComputation
может быть изменен без кастинга.