четверг, 17 февраля 2011 г.

42. Как объявить константу в классе? Можно ли объявить дробную константу?

Сначала нужно подумать, что может означать "константа в классе". Попробую использовать относительно реальные примеры, а не мой любимый "class A" :)

Первый случай

Допустим, мы пишем класс Polygon (многоугольник). Мы хотим, чтобы количество вершин задавалось при создании объекта.
class Polygon{
  int vertexes;
public:
  Polygon(int v):vertexes(v){}
}
Таким образом, при создании экземпляра будет необходимо задать количество вершин, так как конструктора по умолчанию уже нет. Все хорошо, но в какой-нибудь функции-члене можно ненароком изменить vertexes, а мы этого не хотим. Тогда и добавляем модификатор const.
const int vertexes;
Значение такой переменной можно задать только в списке инициализации конструктора, как и сделано в примере. А вот так даже и не пытайтесь:
Polygon(int v){vertexes = v;} /*ошибка*/
см. также Страуструп 10.4.6.1. "Необходимая инициализация членов"

Второй случай

У нас есть класс Year, и мы хотим, чтобы задаваемый год не выходил за границы диапазона
const int MIN_YEAR = 1900;
const int MAX_YEAR = 2100;
const int DEFAULT_YEAR = 2011;

class Year{
  int year;
public:
  Year(int y);
};

Year::Year(int y){
  if(y < MIN_YEAR || y > MAX_YEAR){
    y = DEFAULT_YEAR;
  }else{
    year = y;
  }
}
Хорошо было бы, если класс не молчал, а как-то предупреждал о выходе за пределы, например генерировал исключение, но это пока не важно. Я хочу поместить эти константы в класс. Способ из предыдущего примера явно не подходит. Тут явно напрашивается связь со статическими членами. Так и есть, можно использовать статические константные члены.
class Year{
  int year;
  static const int MIN_YEAR = 1900;
  static const int MAX_YEAR = 2100;
  static const int DEFAULT_YEAR;
public:
  Year(int y);
};

const int Year::DEFAULT_YEAR = 2011;

Year::Year(int y){
  if(y < MIN_YEAR || y > MAX_YEAR){
    year = DEFAULT_YEAR;
  }else{
    year = y;
  }
}
Обратили внимание, что DEFAULT_YEAR проинициализирован за пределами класса? Да, можно и так. А с дробными, согласно спецификации, только так.

Можно ли объявить дробную константу?

Вопрос относится ко второму случаю, с первым (класс Polygon) все нормально.
Дробную объявить можно, но проинициализировать только аналогично способу инициализации DEFAULT_YEAR. Однако в спецификации нет явного запрета на:
class A{
  static const double PI  = 3.1415;
}
MinGW на это не ругается, VS не знаю. Почему так сложно с дробными? Я и сам не понял, можно почитать ветку форума, там вроде все выяснили.

Комментариев нет:

Отправить комментарий

Можно использовать теги <b>, <i>