2017-02-09 2 views
1

Итак, я экспериментировал со статическим полей класса (особенно постоянные из них), и у меня в .... это:Это статическое поле класса используется до его создания?

#include <iostream> 
#include <conio.h> 

class Test { 
public: 
    Test() { std::cout << "Constructing (Default CTOR)\n"; } 
    Test(int f) { std::cout << "Constructing (Int arg CTOR)\n"; } 

    void method() const { std::cout << "Already constructed and being used\n"; } 
}; 

class Stack { 
public: 
    // static const Test what{ 5 }; // - "element of type "const Test" can not have an initializer inside of a class" 
    // const Test ok{ 5 }; // now it can (?) 

    static const Test what; 

    Stack() { 
     what.method(); 
    } 

    // Stack() : what{5} {} // can't do that because "what" will be dependent on object creation (which is not how static class fields roll) 
}; 

Stack obj; 

const Test Stack::what{}; 

int main() 
{ 
    _getch(); 
    return 0; 
} 

Выход:

Output

По-видимому, static const Test what в Stack используется до того, как на самом деле был создан (?).

После этого я провел еще одно испытание:

#include <iostream> 
#include <conio.h> 

class Test { 
public: 
    int data; 

    Test() { std::cout << "CONSTRUCTING (Default CTOR)\n"; } // notice, value-initialization of 'data' has been removed 
    Test(int f) : data{ f } { std::cout << "CONSTRUCTING (Int arg CTOR)\n"; } 

    void method() const { std::cout << "ALREADY CONSTRUCTED AND BEING USED :)\n" << data << std::endl; } 
}; 

class Stack { 
public: 
    static const Test what; 

    Stack() { 
     what.method(); 
    } 
}; 

Stack obj; 

const Test Stack::what{ 5 }; 

int main() 
{ 
    obj.what.method(); 

    _getch(); 
    return 0; 
} 

В этом коде я надеялся увидеть какие-то ошибки, но выход закончился выглядеть так:

Output 2

I есть некоторые предположения о том, что здесь происходит, но я не уверен, что они верны. Итак, если они есть, пожалуйста, поправьте меня.

Вот мои предположения:

В основном, статические переменные создаются в самом начале программы (и являются значения инициализирован) и destoyed в самом конце программы (если вы на самом деле закрыть .exe). В моих примерах у меня есть статическая постоянная переменная what в классе Stack, и я думаю, что она создается в начале инициализации моего значения. Вот почему его поле data установлено 0, и мы можем использовать его методы. Но я не думаю, что это правильно, потому что он будет выводить Constructing (Default CTOR) в консоль. Поэтому я немного застрял там ...

Я также не могу понять, почему прокомментированные строки в моем первом примере являются незаконными. Какие правила полей статического/постоянного класса они разрываются точно?

Если у вас есть идеи, что происходит на моих примерах, пожалуйста, объясните это.

Спасибо за внимание.

+0

Я подозреваю, что это связано с тем, что конструктор по умолчанию фактически ничего не модифицирует в объекте. Что произойдет, если вы измените второй конструктор по умолчанию на ': data {1}'? – Barmar

+0

@ Бармар, ничего. Выходные данные все те же, и ошибок нет. –

+0

Потому что вы '#include ' Я не могу скомпилировать ваш код. Если бы вы придерживались стандартного C++, я мог бы помочь вам. – nwp

ответ

1

Статические переменные в области пространства имен (т. Е. Внутри функции) строятся в порядке их определений в исходном файле. Это упорядочение применяется только между переменными в том же исходном файле, а не между разными исходными файлами.

So obj всегда строится до what. Есть ограниченные вещи, которые могут быть сделаны с объектами, которые имеют конструктор, но до того, как был вызван конструктор; и вызов функции-члена не является одним из них (C++ 14 [basic.life] /5.2). Таким образом, вызов what.method() в конструкторе Stack вызывает неопределенное поведение.

+0

А, я вижу. Спасибо за информативный ответ! Таким образом, нуль во втором выходе exmaple должен был быть ошибкой в ​​конце концов :) –

Смежные вопросы