ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Effective C++...33
    일지 2022. 8. 4. 21:25

    가상 함수 대신 쓸 것들도 생각해 두는 주세를 시시때때로 길러 두자

    가상 함수를 대체할 수 있는 방법들

    어떤 공통적인 연산을 수행하는 함수를 구현할 때 가상 함수 대신 다음과 같은 구현도 가능하다.

    • 비가상 함수 인터페이스 관용구 비가상 함수로 가상 함수를 감싸서 가상 함수를 감추는 방법
    • 함수 포인터 전략 패턴 함수 포인터를 이용해 외부 함수를 사용하는 방법
    • tr1::function 전략 패턴 STL 라이브러리를 이용해 일반적인 형태의 함수를 사용하는 방법
    • 고전적인 전략 패턴 공통 연산을 수행하는 함수를 가진 클래스 계열을 생성해 사용하는 방법

     

    비가상 함수 인터페이스 관용구 예제와 특징

    비가상 함수를 호출할 수 있도록 하고 private 가상 함수를 만들어 상속된 클래스에 따라 구현을 달리할 수 있다.


    class GameCharacter {

    public:

       int healthValue() const

        {

            ...

            int retVal = doHealthValue();

            ...

        }

    private:

        virtual int doHealthValue const { ... };

    };


     

    ※ 자유롭게 계산 함수를 구현할 수 있으나 호출 순서는 최상위 함수에서 결정 되어 있다.

     

    함수 포인터 전략 패턴 예제와 특징

    생성자에서 계산에 사용할 함수의 포인터를 받아 실제 계산 시에 사용한다.


    // 실제 계산을 위한 함수

    int defaultHealthCalc(const GameCharacter& gc);

     

    class GameCharacter {

    public:

        // 계산에 사용할 함수 포인터 타입 정의

       typedef int (*HealthCalcFunc)(const GameCharacter&);

     

       int healthValue() const { return healthFunc(*this); }

    private:

        HealthCalcFunc healthFunc;

    };


     

    ※ 같은 타입의 인스턴스도 계산 함수를 다르게 가질 수 있으며, 게임 실행 도중 처리 함수를 바꿀 수도 있다.

     

    tr1::function 전략 패턴 예제와 특징

    함수 포인터 전략 패턴과 동일한 구현이지만 STL 라이브러리를 사용하여 조금 더 범용성을 높였다.


    class GameCharacter {

    public:

        // 기존과 같지만 타입이 tr1::function으로 바뀌었다.

       typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;

     

       int healthValue() const { return healthFunc(*this); }

    private:

        HealthCalcFunc healthFunc;

    };


     

    ※ STL 라이브러리를 사용하여 단순히 HealthCalcFunc와 같은 함수뿐만 아니라 그러한 형식을 가진 모든 함수를 사용할 수 있다.

     

    고전적인 전략 패턴 예제와 특징

    가상 계산 함수를 가지는 클래스를 선언해 필요에 따라 상속해 새로운 클래스를 만들어 사용하고 해당 클래스를 전달해 사용하는 방식이다.


    class GameCharacter;

    class HealthCalcFunc {

    public:

        ...

        virtual int calc(const GameCharacter& gc) const { ... }

        ...

    };

    HealthCalcFunc defaultHealthCalc;

     

    class GameCharacter {

    public:

        explicit GameCharacter(HealthCalcFunc *phcf = &defaultHealthCalc)

                : pHealthCalc(phcf) { }

        int healthValue() const { return pHealthCalc->calc(*this); }

    private:

        HealthCalcFunc* pHealthCalc;

    };


     

    ※ 쉽게 이해할 수 있고 계산 클래스의 파생 클래스로 함수를 조절할 수 있는 가능성을 열어뒀다.

     

    댓글

Designed by Tistory.