Когда конструкторы статических членов шаблонных классов вызываются в C ++? - PullRequest
9 голосов
/ 05 августа 2011

Существует много информации о том, когда называются конструкторы статических членов обычных классов.Тем не менее, я вижу странное поведение в отношении классов шаблонов.

Каким должен быть вывод следующей программы?(Заметьте, я использую printf, чтобы избежать каких-либо статических осложнений порядка инициализации с std :: cout.)

#include <iostream>

class B {
public:
  B(const std::string &s) { printf("Hello I am B from %s\n", s.c_str()); }
};

template<typename T>
class Atempl {
public:
  static B b_;
};

class A {
public:
  static B b_;
};

template<typename T>
B Atempl<T>::b_("Atempl");
B A::b_("A");

class C : public Atempl<int> {
};

int main(int argc, const char *argv[]) {
  return 0;
}

Я думаю, что вывод должен быть:

Hello I am B from A
Hello I am B from Atempl

Но с g ++ 4.3 наFreeBSD 7.3 Я получаю:

Hello I am B from A

Если добавить строку

template class Atempl<int>;

, все в порядке, и я получаю ожидаемый результат.Вопрос в том, почему объявление класса C не считается экземпляром шаблона Atempl и не вызывает конструктор B?Это часть стандарта или ошибка в g ++ 4.3?

Ответы [ 3 ]

10 голосов
/ 05 августа 2011

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

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

Без явного создания экземпляра вы можете сделать что-то вроде B* p = &Atempl<int>::b_; (или любое другое использование статического члена) для запуска создания экземпляра.

3 голосов
/ 05 августа 2011

При инициализации статического члена шаблона класса не указывается.Фактически, если вы не используете статический элемент, он не должен создаваться и никогда не инициализироваться.Если вы явно создаете экземпляр шаблона, вы инициируете создание экземпляров всех элементов, что, в свою очередь, инициирует инициализацию (но я думаю, что точно, когда он будет инициализирован, все еще не определено).

0 голосов
/ 05 августа 2011

Они вызываются средой выполнения C ++ через некоторое время после запуска процесса и до вызова main(). Нет разницы между «обычными» классами и экземплярами шаблонов классов. Порядок, в котором вызываются конструкторы, не определен.

...