2008-12-01 3 views
0

Я написал программу, которая была в одном файле, и методы были объявлены в заголовке. Первоначально программа работала отлично, когда она была в одном файле. Но когда я отделил программу, я продолжал получать случайные вхождения для деструктора одного из классов, который был объявлен в файле заголовка.Статические переменные, отдельная компиляция

У меня есть статическая переменная в моем заголовке, чтобы подсчитать количество объектов определенного класса. Всякий раз, когда я создаю объект, я увеличиваю эту переменную. Затем в моем деструкторе я вычитаю 1 из этой переменной, проверьте, равен ли он 0 (что означает последний объект) и что-то делать. Иногда значение кажется выключенным, я не знаю, почему. У меня есть случайные вызовы в моем приложении, но я не понимаю, почему это повлияло бы на то, что я описал выше, спасибо. Любая помощь или проницательность оценены!

[Обновить]: есть базовый класс, который содержит деструктор, который реализован в заголовке, тогда у меня есть два производных класса, которые в своем конструкторе увеличивают статический var .. так что я могу сделать?

То, что я пытаюсь сделать, это следующее: В моем заголовке я это:

class A { 
public: 
    virtual ~A() { 
     count --; 
     if (count == 0) { /* this is the last one, do something */ } 
    } 

class B : public A { 
public: 
    B(); 
} 

Тогда в классе BI имеют

B::B() { 
    count++; 
} 

Где я могу определить подсчитывать, так что я не получить вводящие в заблуждение подсчеты? Благодарю.

+0

Причина, по которой он иногда не добавляет происходит потому, что компилятор автоматически генерировать конструктор копирования для вас. Конструктор копии по умолчанию не будет увеличивать значение счетчика. –

ответ

0
class A { 
public: 
    virtual ~A() { 
     count --; 
     if (count == 0) { // this is the last one, do something } 
    } 
protected: 
    static int count; 
}; 

class B : public A{ 
public: 
B(); 
}; 

И тогда в одном и только одном из исходных файлов вам необходимо поставить следующее. Он должен находиться в исходном файле, который содержит код для класса А.

int A::count(0); 

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

+0

Все еще не правильно. –

+0

@ Мартин, конечно, вы правы. Я отвечу на ваш ответ. –

+0

@Mark R: Спасибо. –

0

Можете ли вы уточнить, что вы подразумеваете под «значением, кажется, выключено»? У вас слишком много конструкций? Недостаточно разрушений? Если вы получите слишком много конструкций и не достаточно разрушений, это не будет иметь ничего общего со статикой.

Кроме того, что вы подразумеваете под статической переменной? Вы имеете в виду статическое поле члена или фактическую статическую переменную?

Если вы объявляете только статическую переменную в заголовке (что я сомневаюсь, что вы это делаете), то каждый файл C, содержащий этот заголовок, будет иметь отдельный экземпляр этой переменной (поскольку static перед глобальной переменной означает, что это ограниченный этим объектным файлом).

+0

У меня есть статическая переменная в моем заголовке, где еще я могу ее поместить, потому что мой деструктор определен в заголовке, и он использует эту переменную, спасибо. – BobS

+0

@BobS, статическая переменная часть класса или вне блока класса? Вы, вероятно, хотите этого в своем классе. Кроме того, вам необходимо определить (?) Его в одном из ваших .cpp-файлов, чтобы он был экспортирован один раз. – strager

+0

У меня есть базовый класс, который содержит деструктор .. который реализован в заголовке, тогда у меня есть два производных класса, которые в своем конструкторе увеличивают статический var .. так что я могу сделать? – BobS

1

Где ваша статическая переменная определена? Возможно, вы случайно определяете его в файле заголовка, а вложение - это путающие вещи (и компилятор не поймает несколько определений, которые были бы странными, но вы никогда не знаете).

Убедитесь, что статическая переменная класса определена точно в одной единицы перевода. Вы определяете это следующим образом:

int MyClass::static_var; 

Это также место, куда вы помещаете инициализатор, если таковой имеется.

+0

Привет, в моем заголовке у меня есть деструктор, который нужно будет вызвать static_var. Но мне также нужно вызвать static_var в моем конструкторе для двух моих производных классов, поэтому, где я могу разместить эту строку? – BobS

6

Вы должны определить конструктор в A (все из них), чтобы увеличить счетчик.

Примечание, если не определить их компилятор автоматически генерирует следующие четыре метода:

  • По умолчанию конструктор (если нет другой конструктор не определен)
  • По умолчанию Destructor
  • Конструктор копирования
  • Оператор присваивания

Следующий код переопределяет значения по умолчанию для компилятора, так что y ou должен получить точный счет.

class A 
{ 
    static int count; 

    public: 
     A() // Default constructor. 
     { 
      ++count; 
     } 
     A(A const& copy) // Copy constructor/ 
     {     // Note If you do not define it the compiler 
      ++count;  // will automatically do it for you 
     } 
     virtual ~A() 
     { 
      --count; 
      if (count == 0) 
      { // PLOP 
      } 
     } 
     // A& operator=(A const& copy) 
     // do not need to override this as object has 
     // already been created and accounted for. 
}; 

//// В исходном файле:

int A::count = 0;