More C++ Idioms/Calling Virtuals During Initialization

진영민·2022년 8월 7일
1

More C++ Idioms

목록 보기
8/10

용어 정리

dynamic binding

동적 바인딩, 런타임에 성격이 결정되는 것
반대는 static binding이 있으며, static binding은 컴파일 시간에 성격이 결정되어 런타임 시간이 짧다.

Curiously Recurring Template Pattern idiom

CRTP, 클래스 X가 X자신을 템플릿 인자로 사용하여 인스턴스화 되는 클래스 템플릿으로 파생됨.

// The Curiously Recurring Template Pattern (CRTP)
template <typename T>
struct base
{
    // ...
};
struct derived : base<derived>
{
    // ...
};

동기

개체가 초기화되는 동안 derived class의 가상 함수를 호출하는 것이 좋은 경우가 있다.
언어는 이러한 방법이 위험하기 때문에 이러한 일이 발생하지 않도록 금지한다.
가상 함수가 구성 중인 개체의 데이터 멤버에 액세스하지 않는 경우 문제가 없지만, 이를 보장할 일반적인 방법이 없다.

가능한 접근 방식은 두 가지가 있다.

2단계 초기화

객체 생성과 상태 초기화를 분리한다. 이러한 분리가 항상 가능한 것은 아니다.

class Base {
 public:
   void init();  // May or may not be virtual.
   ...
   virtual void foo(int n) const;  // Often pure virtual.
   virtual double bar() const;     // Often pure virtual.
 };
 
 void Base::init()
 {
   ... foo(42) ... bar() ...
   // Most of this is copied from the original Base::Base().
 }
 
 class Derived : public Base {
 public:
   Derived (const char *);
   virtual void foo(int n) const;
   virtual double bar() const;
 };

non-member function을 이용

class Base {
  public:
    template <class D, class Parameter>
    static std::unique_ptr <Base> Create (Parameter p)
    {
       std::unique_ptr <Base> ptr (new D (p));       
       ptr->init (); 
       return ptr;
    }
};

int main ()
{
  std::unique_ptr <Base> b = Base::Create <Derived> ("para");
}

단상 초기화

Curiously Recurring Template Pattern idiom을 사용한다.

class Base {
};
template <class D>
class InitTimeCaller : public Base {
  protected:
    InitTimeCaller () {
       D::foo ();
       D::bar ();
    }
};

class Derived : public InitTimeCaller <Derived> 
{
  public:
    Derived () : InitTimeCaller <Derived> () {
		cout << "Derived::Derived()" << std::endl;
	}
    static void foo () {
		cout << "Derived::foo()" << std::endl;
	}
    static void bar () {
		cout << "Derived::bar()" << std::endl;
	}
};
profile
코린이

0개의 댓글