Инициализация статического поля в шаблонном классе в C ++ - PullRequest
5 голосов
/ 09 февраля 2012

Я пытаюсь создать несколько саморегистрационных классов на C ++. Поэтому я попробовал решение, аналогичное приведенному здесь . Делая это, я спотыкаюсь о чем-то странном.

Вот код:

#include <iostream>

class StaticClassType {
public:
  StaticClassType() {
    // Notify when the static member is created
    std::cout << "We're in." << std::endl;
  }
};


template<typename T>
class TestClass1 {
public:
  TestClass1() { &m; }
private:
  // Static member in a template class
  static StaticClassType m;
};

template<typename T>
StaticClassType TestClass1<T>::m;


class TestClass2 : public TestClass1<TestClass2> {
public:
  TestClass2() { } // required; why?
};


int main() {
  return 0;
}

Этот код создает статическую переменную-член TestClass1::m при запуске (тем самым выводя на консоль «Мы находимся».) - т.е. Однако код работает, только если я напишу (пустой) конструктор для TestClass2 (как показано в примере).

Зачем мне писать этот конструктор? Почему конструктор по умолчанию, сгенерированный компилятором, не делает то же самое?

Эта проблема возникает только для шаблонных классов. Если TestClass1 не является классом шаблона, код будет работать без написания пустого конструктора для TestClass2.

Ответы [ 2 ]

2 голосов
/ 09 февраля 2012

Я создал еще меньший пример (без конструкторов, которые не нужны):

#include <iostream>

class StaticClassType {
public:
  StaticClassType(int v) {
    // Notify when the static member is created
    std::cout << "We're in."<<v << std::endl;
  }
};


template<typename T>
class TestClass1 {
protected:
  // Static member in a template class
  static StaticClassType m;
};

template<typename T>
StaticClassType TestClass1<T>::m = StaticClassType(3);


class TestClass2 : public TestClass1<TestClass2> {
public:
    void foo()
    {
        (void)m;
    }
};

int main() {
  std::cout << "main" << std::endl;
}

обратите внимание, что необходим метод foo (), иначе компилятор удаляет статическую переменную, поскольку он нигде не используется.

0 голосов
/ 09 февраля 2012

С моей точки зрения, проблема заключается в том, что в «мире шаблонов» компилятор будет генерировать только то, что действительно используется клиентским кодом. Здесь Вы никогда не создаете экземпляр класса TestClass2. Поэтому много кода не будет сгенерировано. Попробуйте:

int main() {

  TestClass2 instance;
  return 0;
} 

И тогда это работает.

...