Сначала нужно подумать, что может означать "константа в классе". Попробую использовать относительно реальные примеры, а не мой любимый "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 не знаю. Почему так сложно с дробными? Я и сам не понял, можно почитать
ветку форума, там вроде все выяснили.