Чем отличается «const» в C и C ++? - PullRequest
13 голосов
/ 20 декабря 2010

Чем квалификация const для переменных отличается в C и C ++?

от: Означает ли "const" только чтение или что-то еще?

"Этот вопрос вызвал ответ: https://stackoverflow.com/questions/4024318#4024417, где он заявляет, что const «просто» означает «только для чтения» на языке C. Я думал, что это все означает const, независимо от того, был ли это C или C ++. Что он имеет в виду? »

Ответы [ 2 ]

8 голосов
/ 20 декабря 2010

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, поскольку метка регистра не сводится к целочисленной константе

7 голосов
/ 20 декабря 2010

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 и C ++.


В 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 метод вызывается для const A a2. Можно отбросить const -несс ...

    std::cout << ((A&)a2).getValue() << std::endl;            // C-style cast
    std::cout << const_cast<A&>(a2).getValue() << std::endl;  // C++-style cast

Второй вариант предпочтительнее, потому что компилятор проверит, что преобразуется только const, и ничего больше. Тем не менее, это все еще не идеально. Вместо этого в класс должен быть добавлен новый метод.

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 может быть видоизменен без приведения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...