Другие языки программирования и технологии

Что за ключевые слова extern и static в С++?

Сам ими не пользуюсь, но иногда встречаются такие выражения. Для чего они нужны и чем отличается static переменная от обычной?
Вообще-то они еще в Си были.

extern - переменная где-то объявлена, но не в этой единице компиляции. Модуль с выделенной памятью будет подключен при линковке.

static - в зависимости от места может значить разные вещи.

Если внутри функции - то переменная выделяется не на стеке, а в сегденте данных - слкдовательно, сохраняет свои значения между вызовами функции.

int how_many_called() /*возвращает сколько раз ее вызвали*/
{
static int count = 0;
return ++count;
}

Если вне функции - как глобалочка, то это означает, что переменная имеет область видимости, ограниченную данной единицей компиляции. Т. е. здесь она видна как глобалочка, но в другом модуле может существовать другая статическая перемнная с таким именем и они не пересекутся.. .

file1.c:

static int x = 10;

file2.c:

static char* x = "hello world";

В С++ static используется в том числе и для объявления статических переменных и функций класса:

переменные существуют в единственном экземпляре и являются общими для всех объектов. Кроме того, их нужно определять отдельно в одной из единиц компиляции проекта.

Методы при вызове не получают указатель на структуру данных класса, так что им недоступны нормальные поля класса, а только статические. Но это же позволяет вызывать статические методы даже когда ни одного объекта класса не создано, через синтаксис имя_класса:: статический_метод ()

class Singleton
{
private:
static Singleton* obj;
Singleton(){}
public:
static Singleton* factory(){if(obj == 0) obj = new Singleton; return obj;}
};

А вот здесь определяем статическую переменную-поле класса
Singleton* Singleton::obj = 0;

int main()
{
Singleton* obj = Singleton::factory(); // еще ни одного объекта не создано, а мы уже можем дернуть статический метод.. .

return 0;
}
Игорь Камбур
Игорь Камбур
84 349
Лучший ответ
1)Иногда в много-файловой сборке в одном из файлов нужно использовать переменную, которая уже используется в другом файле. Если её объявить как extern,то не нужно будет инклудить весь файл. Компилятор сам найдёт эту переменную в другом месте программы.

2)Объявлять переменную как static полезно в двух случаях.
а) Если это локальная переменная внутри ф-ции, то между вызовами ф-ции эта статическая переменная сохранит своё значение и не будет уничтожена. Обычные локальные переменные уничтожаются при выходе из ф-ции.
б) Если это переменная член-класса, то она будет привязана к классу, а не к объектам класса. Для всех объектов данного класса будет создана одна общая переменная (или метод) в специальной области памяти. К такой переменной обращаются не через имя объекта, а через имя класса.
Олег Раитин на счёт Extern -а:

Но в таком случае она будет видна во всём проекте.
А при инклуде только в проинклуденых файлах. Верно?
extern - это указание на внешнюю переменную. Например сама переменная объявлена в одном модуле, но используется в другом. static - это фиксированное значение переменной, которое не меняется с выполнением программы. Вроде константы.
Вася Трифонов
Вася Трифонов
1 059
Игорь Камбур Двойка тебе по теме static. Попадись мне на экзамене - прибью табуреткой! =8-Е]
Если в файле bmp.cpp у тебя есть функция load, то в файле bmp.h пиши extern load() и когда у тебя в нескольких *.cpp будет подключен bmp.h, то программа скопилируется и всё будет работать.
Если в bmp.h написал load() без extern и проиисходит подключение bmp.h в нескольких *.cpp, то программа скопилируется, но у тебя будет дублирование функции load().

Если в bmp.h есть extern ПЕРЕМЕННАЯ, а bmp.cpp содержит эту переменную и bmp.h подключается несколько раз, то программа скопилируется.
Если в bmp.h есть ПЕРЕМЕННАЯ без extern и bmp.h подключается несколько раз, то программа не скопилируется (дублирование переменной) .

Если в класса class есть статическия функция static power, то её можно вызвать без объявления объекте (class.power).
Если в класса class есть не статическия функция power, то вызвать её без объявления объекта нельзя.

Если в функции есть статическая переменная, то она сохранит своё значение после выполнения работы функции и при повторным выполнении функии этим значением можно воспользоваться.