반응형

http://blog.naver.com/wonjinho81?Redirect=Log&logNo=90162829555



순수 가상 함수가 하나도 없는 클래스를 추상 클래스로 만들고 싶을때에는 소멸자를 순수 가상 함수로 만든다.

당연한 얘기겠지만 하위 클래스의 소멸자가 호출된후 기반클래스 소멸자도 호출이 되므로

순수 가상 소멸자의 정의를 반드시 해줘야한다.

 

 

class MyClass {

  MyClass ();

  virtual ~MyClass () = 0;

};

 

MyClass::~MyClass() {}







순수 가상함수란? 추상 클래스를정의할때의 추상 클래스로부터 파생한 클래스가 무엇이건

그 함수만은 반드시 구현해야 한다는 것을 알려주는 것이라고 볼 수 있겠다..

 

 

추상 클래스를 상속받아서 파생클래스를 만들경우를 생각해보자

 

예를들어 전기제품에는 "전원을 켜다 power_on" 이라는 동작이 있을 것이다.

 

전기제품은 어디까지나 "전기를 사용하는 제품" 이라는 실체가 없는 개념적인 단어이기에

이를 추상클래스로 사용할 것이며 TV와 플레이 스테이션은 이를 상속받아 전원을 넣고 무엇을 할 것인가에 

대한 동작을 구현 하면 된다.

 

또한 추상클래스로 하려면 클래스가 가진 함수중 하나라도 순수 가상함수로써 정의하면 된다.

(추상 클래스와 인터페이스를 헷갈리는 경우가 많은데, 추상클래스는 일반 멤버, 함수, 순수가상함수등을 

모두 포함한 클래스를 말하며 인터페이스는 모두 순수가상함수로 이루어진것을 말한다)

 

class AbstractElectronics

{
    public:
        virtual void power_on() = 0;
        virtual ~AbstractElectronics();
};

AbstractElectronics::~AbstractElectronics(){}


//TV
class Television : public AbstractElectronics
{
    public:
        void power_on(){ cout << "Television Power ON !!" << endl; }
};

// 플레이 스테이션
class PlayStation : public AbstractElectronics
{
    public:
        void power_on(){ cout << "PlayStation Power ON !!" << endl; }
};

int main()
{
    // AbstractElectronics *pElectronic = new AbstractElectronics(); // 생성할수없음

    AbstractElectronics *pTV = new Television();
    AbstractElectronics *pPlayStation = new PlayStation();

    pTV->power_on();
    pPlayStation->power_on();

    delete pTV;
    delete pPlayStation;

    return EXIT_SUCCESS;
}

 

// AbstractElectronics *pElectronic = new AbstractElectronics();가 되지 않는것은

power_on(이라는 동작이 구체적으로 정의되어 있지 않기 때문이다.

 

 

 순수 가상 소멸자가 필요한 경우

 

순서가 이미 결정되어거나 기본동작이 이미 있는 것을 추상화 한다고 생각해보자

 

예를들어 칼(날붙이류)를 생각해보자.

칼은 "자르다" 라는 동작이 있다.

 

잘드는 나이프도 식칼도 투핸디드소드도 마찬가지일것이다.(이들을 통틀어 "칼"이라고 부를 뿐..)

여기서도 마찬가지로 "칼" 이란것은 개념으로 칼의 실체는 존재하지 않는다.

"칼"의 실체 자체는 식칼이나 투핸디드소드를 말한다.

 

따라서 "칼"이란 추상화한것이라고 할 수 있다

구현하면 다음과 같다.

 

class AbstractCutlery

{
    public:
        virtual void cut(){ cout << "Cut" << endl; } // 기본 동작
        virtual ~AbstractCutlery();
};

AbstractCutlery::~AbstractCutlery(){}


//구현할 것이 따로 없다
class Kitchenknife : public AbstractCutlery{};
class TwoHandedSword : public AbstractCutlery{};

int main()
{
    AbstractCutlery * pCutlery = new AbstractCutlery();        //이게 문제!!
    AbstractCutlery * pTHSword = new TwoHandedSword();
    AbstractCutlery * pKitchinKnife = new Kitchenknife();

    pCutlery->cut();
    pTHSword->cut();
    pKitchinKnife->cut();

    delete pCutlery;
    delete pTHSword;
    delete pKitchinKnife;

    return EXIT_SUCCESS;
}

 

칼의 기본동작인 자르다 cut은 추상클래스에서 의미 구체적으로 정의되어 있다.

그러나 소스코드에서와 같이 이대로는 추상클래스인 Cutlery까지 인스턴스화할수 있다.

 

순수가상함수가 없기 때문에 추상클래스로써의 기능을 하고 있지 않아서 이다.

이 동작은 원래의 의도가 아니다.

 

이럴때 순수가상소멸자를 사용한다.

순수가상함수가 존재하는것을 컴파일러에에게 알려줌으로써 이 클래스는 추상클래스로써의  역할을 하는 것이다.

 

그냥 소멸자에 평소 순수가상함수처럼 만들듯이 사용하면 된다.

 virtual ~AbstractCutlery() = 0;

 

추상 클래스를 상속한 파생클래스에서는 순수 가상함수 내부를 구현해야 하는데.

소멸자는 모든 클래스에서 반드시 정의해야 하므로( 또는 정의 되어 있으므로 (기본 소멸자)), 

추상클래스로 역할이 필요할때에 적합하다고 할 수 있다.

 

만일 전기제품에서 power_on을 순수가상함수로 정의하고선 추상 클래스에서 내부를 구현한 경우에는

파생 클래스에서 상속 받은 함수를 호출 하는 것도 가능하고

power_on 자체가 순수가상함수이기에 의 AbstractElectronics  인스턴스화를 하지 못하도록 방지하는것도 할 수 있다.

 

 class AbstractElectronics

{
    public:
        virtual void power_on() = 0;
        virtual ~AbstractElectronics();
};

AbstractElectronics::~AbstractElectronics(){} 

 

//추상클래스에서 내부를 구현
void AbstractElectronics::power_on()
{
    cout << "AbstractElectronics Power ON !!" << endl;
}



//TV
class Television : public AbstractElectronics
{
    public:
        void power_on()
        {
            AbstractElectronics::power_on();
            cout << "Television Power ON !!" << endl;
        }
};

// 플레이 스테이션
class PlayStation : public AbstractElectronics
{
    public:
        void power_on()
        {
            AbstractElectronics::power_on();
            cout << "PlayStation Power ON !!" << endl;
        }
};



int main()
{
    // AbstractElectronics *pElectronic = new AbstractElectronics(); // 생성할수없음

    AbstractElectronics *pTV = new Television();
    AbstractElectronics *pPlayStation = new PlayStation();

    pTV->power_on();
    pPlayStation->power_on();

    delete pTV;
    delete pPlayStation;

    return EXIT_SUCCESS;
}

 

 

 

 

그림이 영 없으니...

 

반응형

+ Recent posts