|
지적을 해 달라고 하셔서 몇 자 도움을 드리겠습니다.
일반적으로 전역변수는 어떤 모듈 혹은 객체에서도 접근이 가능하여 변수의 접근 범위 제한이
없어서 매우 편리하고, 복잡한 방법을 쓰지 않고도 코딩이 가능합니다.
다만, 전역변수는 모든 기초 관련 내용에서 제한적으로사용하도록 권장을 하는데,
다음과 같은 이유 때문입니다.
일단, 객체지향 프로그래밍을 떠나서 무한한 자유도를 가진 변수는 그 만큼 관리하기 어렵다는 말과 같은 뜻입니다.
단일쓰레드 프로그램에서야 그런대로 쓸 수 있겠지만(그 것도 모듈의 재사용성면을 보자면 문제가 있지만),
멀티쓰레드로 넘어오면 동기화를 하지 않으면 사실상 관리가 불가능하죠.
그런데, 이런 동기화를 한다는 것은 성능을 떨어뜨리게 되는것이고, 결국 전역변수 보단, 로컬변수가
쓰레드 단위로 작동하는데는 관리적인 측면에서 더 효율적일 수 있습니다. 오류발생도 적어지고요.
단일쓰레드 프로그래밍에서도 특정 모듈을 재 활용하기 위해 분리작업을 한다면 가장 고통스러운 것이 전역변수들 입니다.
(이런 작업 해 보신 분 있다면 아시겠지만....)
그래서 전역변수를 남발하지 말라고 하는 것입니다.
-> 이런 내용과 관련해서는 Code Complete 라는 책을 보시면 자세히 나와 있습니다. 참조 바랍니다.
그렇다고해서 전역변수를 전혀쓰지 말아야 하는 것은 아닙니다.
때론 매우 편리한 점이 많죠.
객체지향 프로그래밍에서도 이런것들을 static으로 처리하도록 열어 주고 있지 않습니까?
단, 객체와 같은 단위로 취급이 가능하도록 처리해 주고 있습니다.
디자인 패턴을 보시면, singleton 객체 생성을 통해 정해진 규칙대로 사용을 권장하고 있습니다.
아마도 이 방법이 가장 좋은 방법이 아닐까 싶네요. 저도 많이 사용하는 방법입니다.
다음과 같이 전역 인스턴스 방식으로 전역변수를 구현하시면 됩니다.
물론 멀티쓰레드에서는 동기화해 줘야 합니다.
아래의 내용 참조 바랍니다.
<Test.h>
class Test
{
public:
static Test* GetInstance();
static void Dispose();
private:
static Test* m_pThis;
}
<Test.cpp>
//
// Singleton instance of the object
//
Test* Test::m_cpInstance = 0;
//-----------------------------------------------------------------------------
// Get the instance of the singleton object
//-----------------------------------------------------------------------------
Test* Test::GetInstance()
{
if( !m_pThis )
{
m_pThis= new Test();
}
return m_pThis;
}
//-----------------------------------------------------------------------------
// Dispose the singleton object
//-----------------------------------------------------------------------------
void Test::Dispose()
{
if( m_pThis)
{
delete m_pThis;
m_pThis= 0;
}
}
<<사용방법>>
//필요한 곳 아무데서나 최초로 호출되면 싱글 인스턴스로 생성이 됩니다.
Test* t = Test::GetInstance();
t->매쏘드();
Test::GetInstance()->매쏘드(); <- 이렇게 사용하기도 합니다.
//해제할 경우
Test::Dispose();
빌더초보 님이 쓰신 글 :
: 일단 제가 알기론 그런경우 전역변수로 선언해야 되는게 맞습니다만,
:
: 질문 한 이유가 '자잘한 전역변수가 많아지는게 보기싫다' 라고 생각되어 적어봅니다.
:
:
: 만약 그런 경우라면 TList를 사용하는 방법이 있습니다.
: TList는 모든 type의 포인터를 담을수 있으니까요.
: 대신 TList에 어떤게 담겨있는지 구별하는 변수정도는 있어야겠죠.
: 예를 들어 List_GlobalClass 라는 TList 를 선언하고, 여기에 담아서 쓰려는 객체가 A, B 두개 일때,
:
: vector<unsigned char> ListType;
:
: 이런식으로 따로 가변 배열을 전역 변수로 선언해서 (만약 객체의 갯수가 256 개가 넘는다면, unsigned short로...)
:
: List_GlobalClass->Add(A);
: ListType.push_back(0);
:
: List_GlobalClass->Add(B);
: ListType.push_back(1);
:
: 이런식으로 구분하면, 두개의 전역변수(TList, vector)로 모든 type의 변수를 Control (생성, 사용, 해제) 할 수 있는거죠.
:
: TList에서 포인터를 꺼내 쓸때 자료형을 확인하는 방법이 존재하는지 몰라서 따로 vector를 써야되겠다는 거고
: 만약 존재한다면 이런 뻘짓은 안해도 될것 같네요.
: (생각 해보니 TObject를 상속받은 class 라면 TObject*로 캐스팅해서 ClassName() 함수를 호출해도 되긴 하겠군요...)
:
:
: 어쨋든, 질문의 의도에 부합했는지 모르겠네요.
:
:
:
: P.S.
:
: 작성자가 아니더라도 제가 적은 내용에 오류가 있으면 지적을 해주시기 바랍니다.
: 질게에 답변을 다는 가장 큰 이유가 제가 공부하기 위해서 입니다.
: 답변을 달기 위해선 '정확'해야 되니까, 여기저기 찾아보고 실제로 구현해보고 하면서 얻는게 많거든요.
: 헌데, 잘못된 지식을 퍼트리거나, 잘못된지 모르고 있는건 큰 문제잖아요.
: 그러니 문제가 있는 내용이다 싶으면 귀찮으시더라도 부디 꼭! 지적을 해주시기 바랍니다.
:
:
: 만나바 님이 쓰신 글 :
: : 메소드에서 new를 통해 컴포넌트 객체를 생성한다음에 메모리를 해제할려면
: : 해당 메소드 안에서 메모리를 해제 해야되는걸로 알고 있는데 해당 메소드 안에서 객체의
: : 메모리를 해제하면 메소드 호출시 해당 컴포넌트 객체가 바로 삭제되는거자나요.
: : 지역변수처럼 선언된 객체를 해제 하려면 어떻게 해야할까요? ( 변수들을 다 전역변수로 선언해야할까요?)다 전역변수로 선언해야할까요?)
|