본문 바로가기
프로그래밍/C++

static

by 리뷰하는 (게임)프로그래머_리프TV 2010. 3. 24.




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;
}​