Могу ли я включить глобальный статический член?

Есть несколько глобальных переменных, которые статичны в одном из файлов заголовков. Я вижу, что эти переменные используются в связанных файлах .cc. Итак, похоже, с этим нет проблем.

Мои вопросы:

  • В чем разница между включением глобальной переменной и статической глобальной переменной? Я знаю, что static global не имеет видимости за пределами своего файла. Но не знаю, как это будет работать, если это будет частью .h, который #included.

  • Я написал образец программы и попробовал то же самое. Но я получаю ошибку компиляции в тот момент, когда делаю переменную статической. Когда это просто глобально, это нормально. Итак, есть ли что-то, чего мне не хватает в обычной сборке g ++? (Обратите внимание, что вначале использовалась наша официальная кодовая база, в которой было достаточно make-файлов, файлов .h и всего остального).

Спасибо за помощь !

Вот моя примерная программа:

.h файл:

#include <iostream>

typedef unsigned int uint;

static const int appk=189;

class abc1
{
    public:
        abc1(int x);
        virtual void printVal();

};

.cc файл:

#include "abc1.h"

extern int appk;

abc1::abc1(int x)
{

}

void abc1::printVal()
{
    printf("abc1 print: %d\n", appk);
}

person Manoj    schedule 14.08.2011    source источник


Ответы (3)


(1) Если вы поместите глобальную переменную в файл .h и включите ее в различные файлы .cpp / .cc, то она будет определена несколько раз для каждого файла. Так что, скорее всего, вы получите ошибку компоновщика. Чтобы преодолеть это, в большинстве случаев вы, вероятно, будете использовать ключевое слово extern:

// myfile.h
extern int i;

и определите это только в одной единице перевода:

// somefile.cc
int i;

(2) Если вы поместите static global в .h файл и включите его, вы не получите никаких ошибок, потому что для каждой другой единицы перевода будет другая копия для этой static глобальной переменной. .

// myfile.h
static int i;  // creates a unique and unrelated copy in all .cc file where included

Однако такое использование не рекомендуется; вместо этого лучше использовать безымянный namespace:

namespace {
  int i;
}

Судя по вашему вопросу, я не вижу, что вы должны получить какую-либо ошибку компоновщика для static global.

person iammilind    schedule 14.08.2011

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

Пример:

header.h:

#ifndef H_XXX
#define H_XXX

static int a;

#endif

file1.cpp:

#include "header.h"

// now have access to a variable called "a"

file2.cpp:

#include "header.h"

// now also have access to some "a"

Оба файла имеют доступ к глобальной переменной с именем a, но каждый файл имеет свою собственную отдельную копию, частную для своей единицы перевода, которая не видна снаружи.

В качестве практического примера, я думаю, что cout объявлен как статический глобал, поэтому каждый, кто использует <iostream>, получает свою собственную копию.

person Kerrek SB    schedule 14.08.2011
comment
Почему вы снова говорите extern int appk; в исходном файле? Избавьтесь от этого! Кроме того, глобальные константы неявно статичны - вам нужно только ключевое слово static для глобальных неконстант. - person Kerrek SB; 14.08.2011
comment
Компиляция проходит, но значение равно 0 - person Manoj; 14.08.2011

static переменная имеет внутреннюю связь. Это означает, что если у вас есть статическая переменная a в x.h и вы включаете x.h в два файла, например m.cpp и n.pp, тогда каждый из этих двух файлов получает свою собственную копию a, что означает, что если вы измените его значение в m.cpp, тогда n.cpp будет мы не увидим этого изменения, потому что в каждой единице перевода (.cpp) существуют две переменные с одинаковыми именами. И они независимы друг от друга.

Но если a не является статическим, то при включении x.h в более чем один файл вы получите ошибку множественного определения, потому что каждое включение x.h будет пытаться определить a, но поскольку a не является статическим; теперь у него есть внешняя связь, а это означает, что если он определен в m.cpp, вы получите ошибку при включении x.h в n.cpp (или наоборот). В этом случае вы должны написать x.h как:

//x.h
extern int a;

А затем определите a ровно в одном .cpp файле, либо m.cpp, либо n.cpp, но не в обоих одновременно. Скажи это m.cpp.

//m.cpp
#include "x.h"

int a =10;

И вы сделали. Теперь вы можете включить x.h в любое количество .cpp файлов, а также получить доступ к a, изменить его значение и делать все, что захотите. Любые изменения в нем будут теперь видны всем .cpp файлам.

person Nawaz    schedule 14.08.2011