중요! static member

보물창고·2022년 8월 19일
0

c++ basic 코드누리

목록 보기
31/50
post-thumbnail
post-custom-banner

static 변수는 왜 외부에서 할당해야 함?? 240730

: 멤버 데이터 내의 static 변수는 클래스내에 오로지 한개만 할당되어 있어야 하므로, 외부파일인 cpp에서 할당 즉 초기화를 해놓아야 한다.

여러개의 객체들이 공통의 static 변수를 참고하려면 클래스 헤더에서 정의하는 것이 아니라, 외부 공간에서 한번만 할당한 친구를 찾아야 하지 않을까?

  • 클래스 내에서 안되는 이유는?
    : 참고 사이트
    https://ansohxxn.github.io/cpp/chapter8-10/

  • 내 생각
    : 전문가 c++에서 멤버 데이터 초기화부분을 공부하면서 Object 클래스 를 보면, 멤버데이터 data가 1로 초기화되는 영역도 생성자의 선처리 영역으로 진입한 후에 초기화가 이루어졌고, 객체마다 data 멤버데이터가 생성되었다.
    그렇다면 객체마다 생성되는 것이 아니라 클래스에 단 한번만 할당되는 static의 경우
    선언부에서 정의를 하면 안된다는 것을 도출할 수 있따.

240606 추가

: 전문가 c++

  • static 멤버 변수를 선언하면, 해당 변수는 객체에 속한 것이아니다.
    클래스에 속한 것이고, 반드시 공간을 할당하는 코드를 cpp파일에다 작성해야 한다. 그러지 않으면 링크에러가 발생한다.
    -> 초기화는 cpp 파일에서 해야 한다. 컴파일시에 훑고 지나간다.

  • 일단 뜬금포지만, extern 과 static 차이가 있따.
    extern은 외부 전역이고 ,static 은 내부 전역이다.

링크에러가 왜 발생할까? 왜 외부에 할당해야 할까? 에 대한 내 생각.
static 멤버변수가 있는 클래스의 경우, 객체화를 할 경우, 외부에서 할당하지 않으면 오류 발생한다.
첫번째로는 컴파일을 하게 되면, static 멤버를 프로그램 시작하자마자 생명이 부여되고, 프로그램이 종료될때 소멸한다. (클래스가 한번이라도 생성되지 않아도 반드시 어느 공간에 할당이 되어 있어야 한다. )
그렇다는 것은 객체화가 되는 순간 할당되는 것이 아니라는 것이므로,
클래스의 입장에서는 외부 공간인 cpp에다가 따로 할당을 해야 한다.

재밌는 내용

  • main에서 static 멤버에 대해 get , set하지 않으면 문제가 되지 않음.

  • 그런데 get 하는 순간 문제 발생한다.
    : 링크에러 발생한다.
    -> get하려는 순간 static 공간에 할당되어야 하는 c가 도대체 어디다가
    메모리를 할당한거야??? 없는데??? 그래서 링크에러가 발생한 거다.

  • 외부 공간에다가 할당하면 문제가 되지 않는데. 일단 할당이랑 초기화 하는 부분에 대해 알아보자.
    : 이러한 에러가 발생했다.
    -> 맨 위부분에 할당과 선언부를 구분해야 한다는 내용이 있다.

https://learn.microsoft.com/ko-kr/cpp/error-messages/compiler-errors-2/compiler-error-c2864?view=msvc-170

  • 위의 문제를 해결하는 방법은 const 나 constexpr을 붙이는 방법도 있는데.
    이러한 문제가 발생한 근복적인 이유는 할당을 하지 않아서이다.

  • const 나 constexpr를 붙이지 않는다면, 클래스 헤더 내에서 초기화는 불가하다.

-> 계속 말했는데, static 멤버변수는 객체를 초기화하는 순간이 아니라,
프로그램이 시작되는 순간에 할당되는 것이기에 외부에 할당해야 한다.

  • 외부 공간에서 메모리 할당하면 , 딱히 초기화하지 않으면 0으로 초기화가 이루어진다.

static member data

  • 멤버 이므로 접근 지정자 사용가능함.

  • 그러나 메모리 영역은, 객체에 위치하는 것이 아닌 static 영역에 올라와져 있음.
    -> Problem: 확인하기 위해서 sizeof 로 객체의 크기를 확인하라.
    : 객체의 메모리에 static이 있다면, 8이 출력되어야 함.

  • 반드시 cpp 외부에서 정의를 해야함.
    : 정의를 하지 않아서 링크 에러 발생하는 것을 확인할 수 있다.
    -> 왜 외부에서 할당을 해야하는 이유가 중요하다. 그리고 그 이유를 알아야만 내가 자알 사용할 수 있다.

  • 모든 객체가 공유함.

  • 헤더와 cpp로 분류할 때, 정의는 cpp에서 정의해야 하는 것이 보통이다.

초기화

-> 위의 링크에러 해결함.

생성시점.

: 프로그램 시작시 static 변수 생성됨.

전역변수 extern vs static member

  • 1) 전역변수는 어디서든 접근 가능함.
  • 2) static member는 private에 놓음으로써 오로지 객체를 이용해서만 접근이 가능함.

접근하는 방법.

: 클래스 이름:: 을 이용해 접근하는 것이 가독성에 좋음.
구별을 할 수 있음.

static 아닌 멤버 데이터는 객체(점). 을 사용 obj.data;

static은 obj.data / OBJ::data 2개 모두 다 사용이 가능함.
but, Obj::data로 접근하자!

  • 예시코드
    : private 이지만, 선언시 외부에서도 접근이 가능함.

초기화

정수 계열

  • static const int : 멤버 필드에서 초기화 해야 함. / 외부 정의 불가.
  • static constexpr int : 멤버 필드에서 초기화 해야 함. / 외부 정의 불가.
  • static int : 멤버 필드에서 초기화 불가함. / 외부 정의 가능.

비정수 계열

  • static const double : 멤버 필드 초기화 불가. / 외부 정의 가능.

problem

: 위의 내용을 코드해서 확인하라.

static member function

1. 호출하는 방법.

1) obj.func();
2) OBJ::func();

2. 정적 멤버함수에서의 접근성.

메모리의 어디에 있을까?

  • 정적 멤버 함수는 소속은 객체이지만, 메모리는 static에 있음.
  • 멤버 데이터와 함수의 메모리는 각 객체의 메모리에 있음.

1) 정적 멤버 함수에서 멤버의 데이터 함수 접근 불가능함.
-> 메모리에 놓여진 공간이 다르기 때문임.
2) 멤버 함수에서는 정적 멤버 함수를 호출할 수 있음.
-> 멤버 데이터와 정적 멤버 데이터의 소속은 모두 해당 클래스에 있음.

  • 예시코드
class Car
{
	private : 
    static int cnt; 
    int data;
    
    public : 
    static void foo()    
    {
    	cnt++; // 가능
        data++ // 불가함. 
        goo() // 불가함.
    }
    
    void goo()
    {
    	cnt ++ // 가능
        data++; // 가능.
        foo() // 가능! 
    }
}

problem

: Car 클래스를 만들어라, 객체의 갯수를 세는 static cnt 와
각 객체의 speed , static foo 함수, void goo 함수를 만들고,
foo 에서 2개의 멤버 접근 하라.
goo에서도 2개의 멤버 에 접근해보아라.

profile
🔥🔥🔥
post-custom-banner

0개의 댓글