2017-02-09 8 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

, is가 실제로 생성되기 전에 static const Test whatStack에서 사용되고 있습니다 (?).

는 그 후 나는 다른 테스트 실행 :

#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을 여기에서 일어나는 일에 대해 몇 가지 가정을하고 있지만, 그들이 맞는지 확실하지 않습니다. 그래서, 그들이 있다면, 나를 수정하십시오. 당신이 실제로 당신의 .EXE를 닫을 때 (

는 기본적으로 정적 변수는 프로그램의 맨 끝에 프로그램의 맨 처음에 생성 (및 가치 초기화) 및 destoyed됩니다 여기

내 가정입니다). 예제에서 나는 클래스의 정적 상수 변수 what을 가지고 있으며 내 프로그램의 시작 부분에 값이 초기화되어 있다고 생각합니다. 그래서 그 data 필드가 0으로 설정되고 그 메소드를 사용할 수 있습니다. 그러나 그것이 콘솔에 Constructing (Default CTOR)을 출력했을 것이므로 정확하다고 생각하지 않습니다. 그래서 나는 거기에 조금 붙어 있습니다 ...

제 첫 번째 예제의 주석 처리 된 줄이 왜 불법인지 이해할 수 없습니다. 정적/상수 클래스 필드의 규칙은 정확히 깨지십니까?

내 사례에서 어떤 일이 벌어지고 있는지 알면 설명해주십시오.

감사합니다.

+0

기본 생성자가 실제로 개체에서 아무 것도 수정하지 않는다는 사실과 관련이 있다고 생각됩니다. 두 번째 기본 생성자를': data {1}'로 변경하면 어떻게됩니까? – Barmar

+0

@Barmar, nothing. 출력은 여전히 ​​동일하고 오류가 없습니다. –

+0

'#include '때문에 코드를 컴파일 할 수 없습니다. 당신이 표준 C++에 고착했다면 나는 당신을 도울 수 있었을 것입니다. – nwp

답변

1

네임 스페이스 범위 (즉, 함수 내부가 아닌)의 정적 변수는 소스 파일에서 정의 된 순서대로 구성됩니다. 이 정렬은 동일한 소스 파일의 변수 사이에만 적용되며 다른 소스 파일 간에는 적용되지 않습니다.

따라서 obj은 항상 what 전에 생성됩니다. 생성자를 가지고 있지만 생성자가 호출되기 전에는 객체로 수행 할 수있는 제한된 사항이 있습니다. 멤버 함수를 호출하는 것은 그 중 하나가 아닙니다 (C++ 14 [basic.life] /5.2). 따라서 what.method()Stack의 생성자는 정의되지 않은 동작을 발생시킵니다.

+0

아, 알겠습니다. 유익한 답변 주셔서 감사합니다! 그래서 내 두 번째 exmaple의 출력에서 ​​0은 결국 오류가 발생했습니다. :) –