(qt) c++ 소스를 공부하던중 extern 을 사용한 부분이 궁금해서 질문 드립니다.
글쓴이: pogusm / 작성시간: 목, 2012/10/25 - 1:12오후
http://www.ipcom.at/en/telephony/qjsimple/ 에서 QjSimple-0.6.6-src.zip 소스를 다운받아서
소스 분석도 해보고, 빌드도 해보고 하는 중입니다.
(인터넷전화 및 인스턴트메신저 클라이언트 프로그램 소스입니다. (QT)C++)
아래는 소스코드중 일부를 축약한 것입니다. (소스코드 내에 한글 주석으로 질문을 붙였습니다)
PjCallback *globalPjCallback; PjCallback::PjCallback() { globalPjCallback = this; }
PjCallback.cpp
#include "PjCallback.h" class QjSimple : public QWidget { public: QjSimple(QWidget *parent = 0); ~QjSimple(); private: PjCallback *pjCallback; // 1 - 멤버 변수가 선언되어 있는데 };
qjsimple.h
extern void *globalPjCallback; // 2 - 왜 extern 을 이용해서 globalPjCallback 변수를 선언해서 QjSimple::QjSimple(QWidget *parent) : QWidget(parent) { globalPjCallback = pjCallback = 0; // 3 - 이런식으로 정의하여 pjCallback = new PjCallback(); // 4 - 이렇게 같이 사용하는 걸까요? QObject::connect((PjCallback*)globalPjCallback, SIGNAL(new_log_message(QString)), this, SLOT(dump_log_message(QString)), Qt::QueuedConnection); }
qjsimple.cpp
위와같이 소스코드를 작성해서 얻는 이득이 무엇이기에 저렇게 한걸까요?
그냥 아래와 같이 수정해도 문제없이 실행되는거 같은데 말입니다.
pjCallback = new PjCallback(); QObject::connect(pjCallback , SIGNAL(new_log_message(QString)), this, SLOT(dump_log_message(QString)), Qt::QueuedConnection);
extern을 사용한 이유가 궁금합니다.
감사합니다.
Forums:
객체가 한 프로그램에서 두 개 이상 생성될 필요가
객체가 한 프로그램에서 두 개 이상 생성될 필요가 없는 경우라면,
저런 식으로 외부에만 객체 포인터 하나를 설정해주고 다른 부분에서 초기화하여
객체를 다시 생성할 필요 없이 사용할 수 있으므로 시간이 절약됩니다.
Cocos2d를 이용해 iPhone 게임 만드는 걸 공부하는 중인데, CCDirector라는 클래스가 sharedDirector라는 클래스 메서드를 갖고 있어서
CCDirector를 새롭게 할당할 필요 없이 이 메서드만 사용하면 되더군요. 그와 비슷한 방식 아닐까 합니다.
제 생각은 이렇습니다.
저는 이렇게 생각했습니다.
답변 감사합니다.
"객체가 한 프로그램에서 두 개 이상 생성될 필요가 없는 경우" 라는 이야기를 어디서 들었던것도 같습니다.
아직 이해가 다 되지는 않지만... 좋은 답변 감사합니다.
같은 객체를 공유하기 위해서 입니다. extern으로
같은 객체를 공유하기 위해서 입니다. extern으로 변수를 선언하면 새롭게 메모리를 할당하는게 아니라 링크단계에서 다른 오브젝트파일 (.o파일)에서 같은 이름으로 선언되어있는 변수를 끌어옵니다. '이렇게 해도 잘된다'고 하신 건 새롭게 객체를 할당하고 있기 때문에 서로다른 두개의 객체를 만드는 방법입니다. 만약 PjCallback 이 한번만 생성된다면, 결국 동일한 결과가 될 겁니다. 왜냐면 PjCallback의 생성자에서 글로벌 객체를 초기화 시키고 있기 때문입니다. 이경우는 pjCallback == globalPjCallback 입니다. 만약 여러번 생성한다면 마지막으로 생성한 녀석이 글로벌 객체가 됩니다.
답변 감사합니다.
globalPjCallback = pjCallback = 0;
pjCallback = new PjCallback(); // 첫번째 생성
pjCallback = new PjCallback(); // 두번째 생성 - globalPjCallback 이 가리키는 것.
위처럼 PjCallback 이 2개이상 생성될때,
가장 마지막에 생성된 객체를 가리키는 변수의 용도로 globalPjCallback 를 사용 하는거였군요..
좋은 답변 감사합니다.
그런데
extern으로 변수를 선언하여, 링크단계에서 다른 오브젝트파일에서 같은 이름으로 선언되어있는 변수를 끌어와야만 하는 이유는 아직 잘 모르겠네요..
이렇게 해도 되는거 아닌지... 헷갈리네요 ^^;
extern은 서로 다른 오브젝트 파일간에 객체를
extern은 서로 다른 오브젝트 파일간에 객체를 공유하기 위한 것입니다.
하나의 파일안에서 이렇게 하면 되지 않느냐는 거는 의미가 없습니다.
예를 들어 프로그램 전체에서 설정사항을 하나의 객체로 관리한다면 다음과 같이 되겠죠.
이렇게 구현하는 것이 꼭 좋다는 게 아니라, 이런식으로 쓰일 수 있다는 예이고 그냥 지금 막 떠오르는대로 쓴거라 그다지 좋은 예제가 아닐 수도 있습니다.
암튼 이렇게 해서 컴파일 하면 object_a.o object_b.o main.o 세개의 오브젝트 파일이 나올 텐데, extern 선언이 없으면 각각의 오브젝트에 따로 변수가 선언된 셈이 됩니다.
하지만 지금은 object_a.o의 pref도, object_b.o의 pref도 모두 같은 하나의 Pref에 대한 인스턴스(main.o에서 생성한 인스턴스)를 가리켜야 하므로 extern으로 공유하는 것입니다.
extern 으로 가져오기 보다는, 오브젝트를 생성할 때 Pref에 대한 포인터를 넘겨주는 형식으로 처리할 수도 있을 겁니다.
혹은 객체의 유일성을 보장하기 위해서 싱글톤 패턴을 이용할 수도 있겠죠.
두번 감사합니다
아주 잘 이해가 되었습니다.
"서로 다른 오브젝트 파일간에 객체를 공유"하기 위한 거였군요.
감사합니다.
댓글 달기