Продолжаем захватывающую беседу о возможных использованиях многоликого const
. Начало было тут: Использование const. Часть 1.const
данные в классе
Значения const
данных класса задаются один раз и навсегда в конструкторе.
class CFoo
{
const int num;
public:
CFoo(int anum);
};
CFoo::CFoo(int anum):num(anum)
{
...
}
Интересный момент со static const
данными класса. Вообще для данных целого типа (enum, int, char
) их значения можно задавать прямо в объявлении класса. Вот этот код правильный с точки зрения стандарта:class CFoo
{
public:
static const int num=50;
};
Но в Visual C++ 6.0 такое задание значения не работает, это один из багов Visual C++ 6.0. Тут задавать значение static const
переменной следует отдельно. Не могу сказать, что эта бага меня сильно расстраивает. Вместо того, чтобы запоминать, когда можно при объявлении писать инициализацию, когда нельзя, лучше сразу так написать:class CFoo
{
public:
static const int num ;
};
const int CFoo::num = 20;
const
функции в классеФункция класса, объявленная
const
, трактует this
как указатель на константу. Вообще тип this
в методе класса X
будет X*
. Но если метод класса объявлена как const
, то тип this
будет const X*
. В таких методах не может быть ничего присвоено переменным класса, которые не объявлены как static
или как mutable
(о mutable
потом). Также const
-функции не могут возвращать не const
ссылки и указатели на данные класса и не могут вызывать не const
функции класса. const
-функции иногда называют инспекторами (inspector), а остальные мутаторами (mutator). Я пыталась найти для mutator перевод, который будет звучать получше, но в переводах я ничего подходящего не встречала, а Яндекс.Лингво смог мне предложить только "ртутный вентиль", что сюда явно не подходит.class CFoo
{
public:
int inspect() const; // Эта функция обещает не менять *this
int mutate(); // Эта функция может менять *this
};
В классе могут присутствовать две функции отличающиеся только const
.class CFoo
{
...
public:
int func () const;
int func ();
};
Не всякая функция может быть объявлена константной. Конструкторы и деструкторы не могут быть объявлены как const
. Также не бывает static const
функций.class CFoo
{
int i;
public:
static int func () const; //ошибка
};
Константный классОфициально такого понятия как константный класс (const class) не существует. Но часто под этим понимается объявление вида
const CFoo p;
.Экземпляр класса
CFoo
, объявленный таким образом, обещает сохранить физическое состояние класса, не менять его. Как следствие, он не может вызвать не const
функции класса CFoo
. Все данные, не объявленные как const
, начинают трактоваться как const
. То естьint
становится int const
int *
становится int * const
const int *
становится int const *const
и так далее.
На этом все о
const
, но будет еще отдельный пост о том, как избавиться от const
, то есть о mutable
и const_cast
.Ссылки по теме:
Advice From the C++ Experts: Be Const-Correct
Const Correctness in C++
comp.lang.c++.moderated Const member functions
comp.lang.c++.moderated static const member of class
comp.lang.c++.moderated const classes and const members
Technorati tag: cpp
18 коммент.:
"Но в Visual C++ 6.0 такое задание значения не работает, это один из багов Visual C++ 6.0. Тут задавать значение static const переменной следует отдельно." - это не баг, а требования стандарта. У Шилдта даже об этом написано в описании модификатора const...
это не баг, а требования стандарта.
А можно цитату из стандарта(не из Шилдта :D), где требуется задавать значение отдельно?
Со своей стороны приведу:
IS C++98,C++03.
9.4.2/4
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.
Другими словами Алёна права, только она не упомянула, что, даже указав значение константы прямо в определении класса, всё равно придётся делать определение этой константы как обыкновенного static-data-member, причём, в определении значение константы указываться не должно.
2vova
это не баг, а требования стандарта. У Шилдта даже об этом написано в описании модификатора const...
Тут archimed7592 уже очень подробно ответил, добавить мне нечего.
может mutator это изменятель/изменитель/модификатор ?
хотя "модификатор" уже используется в другом контексте. а "изменятель" как-то слишком забавно звучит
Вообще тип this в методе класса X будет X*
Если быть до конца точным (тем более, что речь идет о const), то указатель this имеет тип X* const
Скажите пожалуйста, если есть член класса-массив в стиле C, то можно ли при его объявлении (в хэдере) указать в качестве размера ранее объявленную static const int? Попробовал, компилятор ругатеся.
Другими словами Алёна права, только она не упомянула, что, даже указав значение константы прямо в определении класса, всё равно придётся делать определение этой константы как обыкновенного static-data-member...
На самом деле это требование только к тому, чтобы компилятор выделил память под константную переменную. Для простых типов можно просто написать в хедере например:
static const int sm_size = 16;
и дальше использовать эту константу, только нельзя использовать операции со взятием адреса этой константы ( &sm_size, передача в функцию, где аргумент передаётся по ссылке) - адреса у этой константы нет, так как ей не выделена память. Чем-то напоминает C-ный:
#define sm_size 16
(но не полный аналог).
Для Игоря:
Например в gcc подобный код компилируется:
class AnyClass {
...
static const int sm_size = 16;
char a[ sm_size ];
...
};
по поводу перевода mutator'а - просто используйте нормальные словари.
http://www.multitran.ru/c/m.exe?l1=2&l2=1&s=mutator
по математической, технической и программной тематике лучше мультитрана я пока не нашёл словаря
Очень хорошеее обяснение по мелодам-консантам
Если в классе присутствуют две функции отличающиеся только const, то как знать какая когда будет визвана?
Если в классе присутствуют две функции отличающиеся только const, то как знать какая когда будет визвана?
Очень может быть, что компилятор выдаст сообщение об ошибке "ambiguous call to a function"
>> В классе могут присутствовать две функции отличающиеся только const.
>> class CFoo
>> {
>> ...
>> public:
>> int func () const;
>> int func ();
>> };
Как компилятор выбирает одну из них?
2Саша К.
const для const объекта и не const для не const объекта. Примеры тут: http://www.parashift.com/c++-faq/const-overloading.html
class Cat
{
public:
Cat (int InitialAge);
~Cat();
int GetAge();
void SetAge (int Age);
void Meow();
private:
int itsAge;
};
когда я в msvc++ 6.0 пытаюсь определить GetAge или Meow, как const - выдаёт ошибку, что дескать не находит перегруженный вариант функции. Хотя в книжке, "как бы", написано, что всё должно быть на ура. Пришлось обойтись без const.
Добрый день. У меня такой вопрос, а как быть с ситуацией на подобии этой:
static const unsigned short Crc16Table[256] = {
0x0000, 0xC0C1, 0xC181, ... //Не стал копировать всю таблицу ибо содержимое к задаче отношения не имеет
};
Собственно вышеприведенный код не компилируется (gcc какой-то там версии). Я не понимаю, почему unsigned short int вдруг оказывается "non-integral type"
error: invalid in-class initialization of static data member of non-integral type 'const short unsigned int [256]'
2Антон Белоусов
Why I can't initialize non-const static member or static array in class? http://stackoverflow.com/questions/9656941/why-i-cant-initialize-non-const-static-member-or-static-array-in-class
то есть const int CFoo::num = 20; нужно писать первой строчкой(или порядок не важен?) в соответствующем cpp-файле? я сам использую такой вариант, вроде работает:
class CFoo
{
public:
enum{ num = 20 };
};
еще слышал, что при записи
class CFoo
{
public:
static const int num = 50;
};
обязательно нужно добавить магическую строчку
const int CFoo::num;
иначе операция взятия адреса сфейлит, глупости все это?
// Example program
#include
int main()
{
const int i =10;
const int* p =&i;
*((int*)(p)) =20;
std::cout<< *((int*)(&i))<<" "<< i<< " "<< &i << " " << p <<"\n";
}
output:
20 10 0x7ffdccf7cbdc 0x7ffdccf7cbdc
Два значения по одному адресу? - почему?
Отправить комментарий