static, 지역변수로 선언되어 있는 변수를 전역 변수처럼 사용한다.
C++, 클래스에서 사용하는 static은 크게 2가지 특징을 가지고 있는데
첫번째로 public안에 선언된 멤버 변수에 static을 붙히면 전역 변수처럼 사용이 가능하다.
(main 함수가 호출 되기 이전에 메모리 공간에서 초기화가 되기 때문이다.)
#include <iostream>
class AAA
{
public:
// public에 static을 선언
static int a;
};
// 일단 이곳에서 초기화를 한번 해주어야 한다.
int AAA::a = 10;
void main()
{
std::cout << AAA::a << std::endl;
// 비록 AAA 클래스 객체를 생성하지 않았어도 사용이 가능하다.
// 물론 이것은 public에 선언되어 있기 때문에 가능한 것이다.
AAA::a = 100;
std::cout << AAA::a << std::endl;
}
두번째로 static 멤버 변수는 멤버에 존재 하는 것이 아니다.
단지 여러 클래스에서 접근 할 수 있는 권한만이 부여된 것이다.
#include <iostream>
class AAA
{
// private에 static을 선언
static int a;
public:
void Set_a(int n)
{
a = n;
}
int Get_a()
{
return a;
}
};
// 일단 이곳에서 초기화를 한번 해주어야 한다.
int AAA::a = 0;
void main()
{
AAA a;
AAA b;
// a 객체에서 static 변수를 접근하여 값을 변경하고
a.Set_a(10);
std::cout << a.Get_a() << std::endl;
std::cout << b.Get_a() << std::endl;
// b 객체에서 static 변수를 접근하여 값을 변경했을 때
b.Set_a(100);
// 양쪽다 값이 바뀌는 것을 알 수 있다.
std::cout << b.Get_a() << std::endl;
std::cout << a.Get_a() << std::endl;
// 정확히는 약쪽의 값이 바뀌는게 아니라 하나의 static 변수를 공용 한다고 보면 된다.
}
그렇다고 만약 BBB라는 클래스가 있다고 하였을때,
AAA의 static a를 접근하여 수정할 수 있는것은 아니다.
static a 는 엄연히 AAA클래스의 private 선언 이기 때문이다.
보통 이는 나중에 디자인 패턴에서 나오는 싱글턴 패턴에서 많이 쓰이게 되는데.
개념은 간단하다.
#include <iostream>
class cursor
{
// 생성자와 복사 생성자를 private에 선언
// 외부에서 생성할 수 없게 만든다.
cursor() {};
// 단하나의 객체만 생성해야 하기 때문에
// 혹시 모를 복사 생성자의 가능성을 미리 막아둔다.
cursor( const cursor& c ) {};
int n;
public:
// GetInstance 함수를 static 함수로 선언.
static cursor& GetInstance()
{
// 객체 생성은 처음에 딱 한번만 된다.
static cursor _Instance;
// 그 이후부턴 _Instance를 return하여 1개의 객체만을 사용.
return _Instance;
}
void SetN(int n )
{
this->n = n;
}
void printN()
{
std::cout << n << std::endl;
}
};
void main()
{
// cursor a; // error 생성자가 private
// cursor b(a); // 당연히 error 마찬가지 이유.
cursor& c1 = cursor::GetInstance();
c1.SetN(10);
cursor& c2 = cursor::GetInstance();
c2.SetN(20);
cursor& c3 = cursor::GetInstance();
c3.SetN(30);
cursor& c4 = cursor::GetInstance();
c4.SetN(40);
c1.printN();
c2.printN();
c3.printN();
c4.printN();
}
결과 화면
단 1개의 객체만으로 값을 접근 하는 것을 확인 할 수 있다.
최종 정리
#include <iostream>
// static
class A
{
public:
// public에 선언한 static 멤버 변수 st_val
static int st_val;
// public에 선언한 멤버 변수 val
int val;
A()
{
st_val++;
std::cout << st_val << std::endl;
}
// 일반 적인 멤버 함수 안에선 멤버 변수, static멤버 변수를 모두 접근, 수정 가능하지만
void method()
{
val = 10;
st_val = 11;
}
// static 멤버 함수 안에서 멤버 변수는 수정 할 수 없다.
// 오로지 static 변수만 가능
static void st_method()
{
// val = 100; // 안된다.
st_val = 200; // static 변수이기 때문에 가능하다.
}
};
// st_val의 초기화
int A::st_val = 0;
void main()
{
A a;
A b;
A c;
// val은 객체 a,b,c가 각각 가지고 있지만
// st_val은 동일한 메모리에 존재하고 있다.
a.val = 10;
a.st_val = 10;
b.st_val = 100;
// 멤버 함수를 사용한다.
a.method();
// static 멤버 함수를 사용한다.
a.st_method();
// 객체 선언을 하지 않고도 public안에 존재하는
// static 멤버 함수를 사용 할 수 있다.
A::st_method();
// 일반 멤버 함수는 사용할 수 없다.
// A::method();
// 멤버 변수도 똑같다.
// A::val = 10;
// static 멤버 변수를 접근
std::cout << A::st_val << std::endl;
// 값 수정
A::st_val = 1000;
// 변경 된 것을 확인 할 수 있다.
std::cout << a.st_val << std::endl;
}
'프로그래밍 > C++' 카테고리의 다른 글
public: private: 그리고 protected: (0) | 2010.03.24 |
---|---|
explicit, mutable (0) | 2010.03.24 |
멤버 이니셜 라이저(member initializer) (0) | 2010.03.23 |
복사 생성자, 디폴트 생성자 그리고 디폴트 복사 생성자. (0) | 2010.03.21 |
friend (0) | 2010.03.21 |