C++의 단일 모드 소개

8643 단어 단일 모드
이러한 기능 모듈 이 필요 한 곳 이 많 습 니 다.예 를 들 어 시스템 로그 출력,GUI 응용 은 단일 마우스 여야 합 니 다.MODEM 의 연결 은 하나의 전화선 만 필요 하고 운영 체 제 는 하나의 창 관리자 만 있 을 수 있 으 며 한 대의 PC 는 하나의 키보드 만 연결 할 수 있 습 니 다.단일 모드 는 여러 가지 실현 방법 이 있 는데 C++에서 심지어 하나의 전역 변수 로 이 점 을 직접 할 수 있 지만 이런 코드 는 매우 우아 하지 않다.전역 대상 을 사용 하면 실례 에 편리 하 게 접근 할 수 있 지만,하나의 대상 만 성명 할 수 는 없다.즉,전역 실례 를 제외 하고 같은 종류의 로 컬 실례 를 만 들 수 있다 는 것 이다.디자인 모드 라 는 책 에서 아주 좋 은 실현 을 보 여 주 었 습 니 다.하나의 사례 류 를 정의 하고 클래스 의 개인 정적 포인터 변수 가 클래스 를 가리 키 는 유일한 인 스 턴 스 를 사용 하 며 공유 하 는 정적 방법 으로 이 인 스 턴 스 를 가 져 옵 니 다.
단일 사례 모델 은 클래스 자 체 를 통 해 유일한 인 스 턴 스 를 관리 하 는데 이런 특성 은 문 제 를 해결 하 는 방법 을 제공 합 니 다.유일한 인 스 턴 스 는 클래스 의 일반 대상 이지 만 이 클래스 를 설계 할 때 하나의 인 스 턴 스 만 만 들 고 이 인 스 턴 스 의 전체 접근 을 제공 할 수 있 습 니 다.유일한 인 스 턴 스 클래스 싱글 톤 은 정적 구성원 함수 에 인 스 턴 스 를 만 드 는 동작 을 숨 깁 니 다.습관 적 으로 이 구성원 함 수 를 인 스 턴 스()라 고 부 르 는데 반환 값 은 유일한 인 스 턴 스 지침 입 니 다.정 의 는 다음 과 같 습 니 다.

class CSingleton
{
//
public:
static CSingleton* GetInstance()
{
      if ( m_pInstance == NULL )  //
        m_pInstance = new CSingleton();
        return m_pInstance;
}
private:
    CSingleton(){};
    static CSingleton * m_pInstance;
};
사용자 가 유일한 인 스 턴 스 에 접근 하 는 방법 은 GetInstance()구성원 함수 밖 에 없습니다.이 함 수 를 통과 하지 않 으 면 인 스 턴 스 를 만 들 려 는 시도 가 실 패 됩 니 다.클래스 의 구조 함수 가 개인 적 이기 때 문 입 니 다.GetInstance()는 게 으 름 으로 초기 화 합 니 다.즉,이 함수 가 처음 방 문 했 을 때 되 돌아 오 는 값 입 니 다.이것 은 방탄 디자인―모든 GetInstance()이후 호출 이 같은 인 스 턴 스 의 지침 으로 되 돌아 가 는 것 이다.
CSingleton* p1 = CSingleton :: GetInstance();CSingleton* p2 = p1->GetInstance();CSingleton & ref = * CSingleton :: GetInstance();
GetInstance 를 조금 만 수정 하면 이 디자인 템 플 릿 은 가 변 다 중 인 스 턴 스 상황 에 적용 할 수 있 습 니 다.예 를 들 어 하나의 클래스 가 최대 5 개의 인 스 턴 스 를 허용 합 니 다.단일 클래스 CSingleton 은 다음 과 같은 특징 이 있 습 니 다.
유일한 인 스 턴 스 를 가리 키 는 정적 포인터 mpInstance,그리고 개인 적 인 것 입 니 다.이 유일한 인 스 턴 스 를 가 져 오고 필요 할 때 이 인 스 턴 스 를 만 들 수 있 는 공유 함수 가 있 습 니 다.그것 의 구조 함 수 는 개인 적 인 것 이기 때문에 다른 곳 에서 이러한 인 스 턴 스 를 만 들 수 없다.대부분의 경우 이런 실현 에는 문제 가 없 을 것 이다.경험 있 는 독자 가 물 어 볼 수 있 습 니 다.mpInstance 가 가리 키 는 공간 은 언제 방출 됩 니까?더 심각 한 문 제 는 이 실례 의 분석 함수 가 언제 실 행 됩 니까?만약 에 이러한 분석 행위 에서 필요 한 조작 이 있다 면 예 를 들 어 파일 을 닫 고 외부 자원 을 방출 하면 위의 코드 는 이 요 구 를 실현 할 수 없다.우 리 는 이 인 스 턴 스 를 정상적으로 삭제 하 는 방법 이 필요 하 다.
프로그램 이 끝 날 때 GetInstance()를 호출 하고 되 돌아 오 는 지침 을 delete 로 떨 어 뜨 릴 수 있 습 니 다.이렇게 하면 기능 을 실현 할 수 있 지만 추 할 뿐만 아니 라 실수 하기 쉽다.이러한 추가 코드 는 쉽게 잊 혀 지고 delete 이후 에 GetInstance 함 수 를 호출 할 코드 가 없다 는 것 을 보장 하기 어렵 기 때문이다.적절 한 방법 은 자신 이 적당 할 때 자신 을 삭제 하거나 자신의 조작 을 삭제 하 는 것 을 운영 체제 의 적당 한 점 에 걸 어 적당 할 때 자동 으로 실행 하도록 하 는 것 이다.우 리 는 프로그램 이 끝 날 때 시스템 이 모든 전역 변 수 를 자동 으로 분석 한 다 는 것 을 안다.사실은 시스템 도 모든 유형의 정적 구성원 변 수 를 분석 할 것 이다.이런 정적 구성원 도 전체 변수 와 같다.이 특징 을 이용 하여 우 리 는 단일 클래스 에서 이러한 정적 구성원 변 수 를 정의 할 수 있 으 며,유일한 작업 은 분석 함수 에서 단일 클래스 의 인 스 턴 스 를 삭제 하 는 것 입 니 다.다음 코드 의 CGarbo 클래스(Garbo 는 쓰레기 노동자 라 는 뜻):

class CSingleton
{
//
public:
static CSingleton* GetInstance();
private:
    CSingleton(){};
    static CSingleton * m_pInstance;
class CGarbo // CSingleton
{
        public:
            ~CGarbo()
            {
                if( CSingleton::m_pInstance )
                  delete CSingleton::m_pInstance;
}
         }
        Static CGabor Garbo; // , ,
};
클래스 CGarbo 는 다른 곳 에서 남용 되 지 않도록 CSingleton 의 개인 내장 클래스 로 정의 된다.프로그램 이 실 행 될 때 시스템 은 CSingleton 의 정적 구성원 인 Garbo 의 분석 함 수 를 호출 합 니 다.이 분석 함 수 는 단일 사례 의 유일한 인 스 턴 스 를 삭제 합 니 다.이런 방법 으로 단일 대상 을 방출 하 는 것 은 다음 과 같은 특징 이 있다.단일 클래스 내부 에서 전문 적 인 플러그 인 클래스 를 정의 한다.단일 클래스 에서 방출 에 사용 되 는 정적 구성원 을 정의 합 니 다.프로그램 이 끝 날 때 전역 변수의 특성 을 분석 하고 최종 방출 시 기 를 선택한다.단일 코드 를 사용 하 는 데 는 어떠한 조작 도 필요 없고 대상 의 방출 에 관심 을 가 질 필요 가 없다.
진일보 한 토론
그러나 정적 대상 을 추가 하면 항상 만 족 스 럽 지 못 하기 때문에 다음 과 같은 방법 으로 단일 사례 를 실현 하고 해당 하 는 문 제 를 해결 하 는 사람 이 있 습 니 다.코드 는 다음 과 같 습 니 다.

class CSingleton
{
    //
    public:
        static Singleton &GetInstance()
{
    static Singleton instance;
    return instance;
}
        private:
            Singleton() {};
};
부분 정적 변 수 를 사용 하여 매우 강력 한 방법 으로 단일 사례 의 특성 을 완전히 실현 하고 코드 의 양 이 더욱 적 으 며 단일 사례 의 소각 문 제 를 걱정 하지 않 아 도 됩 니 다.그러나 이런 방법 을 사용 하 는 것 도 문제 가 생 길 수 있다.다음 과 같은 방법 으로 단 례 를 사용 할 때 문제 가 생 긴 다.
Singleton singleton = Singleton :: GetInstance();
이렇게 하면 복사 와 같은 문제 가 발생 하 는데 이것 은 단일 사례 의 특성 에 위배 된다.이 문제 가 발생 한 이 유 는 컴 파 일 러 가 클래스 에 기본 적 인 구조 함 수 를 생 성하 여 클래스 의 복 사 를 지원 하기 때문이다.마지막 으로 방법 이 없습니다.우 리 는 클래스 복사 와 클래스 할당 을 금지 하고 프로그래머 가 이런 방식 으로 단일 예 를 사용 하 는 것 을 금지 해 야 합 니 다.그 당시 리더 의 뜻 은 GetInstance()함수 가 인용 을 되 돌려 주 는 것 이 아니 라 지침 을 되 돌려 주 는 것 이 었 습 니 다.함수 의 코드 는 다음 과 같 습 니 다.

static Singleton *GetInstance()
{
static  Singleton instance;
return  &instance;
}
그런데 저 는 잘 모 르 겠 어 요.왜 컴 파 일 러 를 이렇게 하지 못 하 게 하 죠?그 제야 나 는 표시 할 수 있 는 생명 류 복사 의 구조 함수 와 과부하=연산 자 를 생각 했다.새로운 사례 는 다음 과 같다.

class Singleton
{
    //
    public:
        static Singleton &GetInstance()
{
    static Singleton instance;
    return instance;
}
        private:
            Singleton() {};
            Singleton(const Singleton);
            Singleton & operate = (const Singleton&);
};
Singleton(const Singleton)에 대하 여;Singleton&operate=(const Singleton&);함수,사적 으로 설명 하고 실현 되 지 않 음 만 설명 해 야 합 니 다.이렇게 하면 위의 방식 으로 단일 예 를 사용 할 때 친구 류 든 다른 것 이 든 컴 파일 러 는 모두 잘못 보고 합 니 다.이런 단일 클래스 에 문제 가 있 을 지 는 모 르 겠 지만 프로그램 에서 이렇게 사용 하 는 것 은 거의 문제 가 없다.
싱글 톤 클래스 를 최적화 하여 단일 라인 응용 싱글 톤 에서 조작 부호 new 를 사용 하여 유일한 실례 로 저장 공간 을 분배 합 니 다.new 조작 자 는 스 레 드 가 안전 하기 때문에 다 중 스 레 드 응용 에서 이 디자인 템 플 릿 을 사용 할 수 있 습 니 다.그러나 하나의 결함 은 프로그램 이 종료 되 기 전에 delete 로 인 스 턴 스 를 파괴 해 야 한 다 는 것 입 니 다.그렇지 않 으 면 메모리 가 넘 칠 뿐만 아니 라 예측 할 수 없 는 행동 도 할 수 있 습 니 다.싱글 톤 의 분석 함수 가 호출 되 지 않 기 때 문 입 니 다.한편,로 컬 정적 인 스 턴 스 를 사용 하여 동적 인 스 턴 스 를 대체 하면 단일 스 레 드 응용 은 이 문 제 를 쉽게 피 할 수 있 습 니 다.다음은 위의 GetInstance()와 조금 다른 실현 입 니 다.이 실현 은 단일 스 레 드 응용 에 사 용 됩 니 다.

CSingleton* CSingleton :: GetInstance()
{
    static CSingleton inst;
    return &inst;
}
로 컬 정적 대상 인 스 턴 스 인 스 턴 스 는 GetInstance()를 처음 호출 할 때 구 조 된 것 으로 프로그램 이 종 료 될 때 까지 활동 상 태 를 유지 합 니 다.포인터 mpInstance 가 불필요 해 지고 클래스 정의 에서 삭제 할 수 있 습 니 다.동적 할당 대상 과 달리 정적 대상 은 프로그램 이 종 료 될 때 자동 으로 소각 되 기 때문에 더 이상 수 동 으로 인 스 턴 스 를 소각 할 필요 가 없습니다.
코드 학습

//
#include <iostream>  
using namespace std;  
// C++   
class Singleton  
{  
private:  
       Singleton();// :   

       static Singleton* instance;//   
       int var;// ( )  
public:  
       static Singleton* GetInstance();// ( )  
       int getVar();// var   
       void setVar(int);// var   
       virtual ~Singleton();
};  
//   
Singleton::Singleton()  
{  
       this->var = 20;  
       cout<<"Singleton Constructor"<<endl;  
}  
Singleton::~Singleton()  
{  
       cout<<"Singleton Destructor"<<endl;
       //delete instance;  
}  
//   
/*Singleton* Singleton::instance=NULL;
Singleton* Singleton::GetInstance()  
{  
       if(NULL==instance)
              instance=new Singleton();
       return instance;  
}*/
Singleton* Singleton::instance=new Singleton;
Singleton* Singleton::GetInstance()  
{  
       return instance;  
}    
//seter && getter   
int Singleton::getVar()  
{  
       return this->var;  
}  
void Singleton::setVar(int var)  
{  
       this->var = var;  
}  
//main  
void main()  
{  
       Singleton *ton1 = Singleton::GetInstance();  
       Singleton *ton2 = Singleton::GetInstance();
      if(ton1==ton2)
              cout<<"ton1==ton2"<<endl;
       cout<<"ton1 var = "<<ton1->getVar()<<endl;
       cout<<"ton2 var = "<<ton2->getVar()<<endl;  
       ton1->setVar(150);  
       cout<<"ton1 var = "<<ton1->getVar()<<endl;
       cout<<"ton2 var = "<<ton2->getVar()<<endl;
       delete Singleton::GetInstance();//
}  

좋은 웹페이지 즐겨찾기