2011-11-25 3 views
0

내 프로그램에서 나는 모든 어려움에 직면하고있다. (나는 그들을 모두 저장하고 많은 문제를 묻는다 : P). 내가 가진 것은 functor이다. 가상 오퍼레이터()를 가지고있는 모든 functor는 DuplicateFn에서 상속 받았으며, 각 자식은 그것의 버전을 쓸 것으로 예상된다.새롭고 공유 된 포인터와 가상 함수

이제 자식 중 하나 인 merge가 성공하지 못할 수 있습니다.이 경우 폴백 메서드를 시도해야합니다. 나는 문제가 여기에 이미 명확하게 볼 수 있습니다 생각

class MergeFn : public DuplicateFn { 
public: 
    MergeFn() : FallBack(new SkipFn()) 
    { 
    } 
    MergeFn(GMProject const* Out, GMProject const* In, DuplicateFn* f) 
     : DuplicateFn(Out, In), FallBack(f) 
    { 
    } 
    virtual void operator() (GMProject::pTree& tOut, const GMProject::pTree& tIn) const { 
     if (!GMProject::isMergeable(tOut.GetName())) { 
      (*FallBack)(tOut, tIn); //virtual table resolves this to the correct class 
     } else { 
     } 
    } 
private: 
    std::shared_ptr<DuplicateFn> FallBack; 
}; 

- 기본이 아닌 생성자에서,이 방법은 주어진 매개 변수의 소유권을 포착 : 같이 현재 클래스 따라서 보인다. - 이것은 내가 원하는 것이 아닙니다. 매개 변수를 복사하고 소유권을 유지해야합니다.
이제 나는 , FallBack(new DuplicateFn(f))을 시도했다. 그러나 이것도 작동하지 않을 것이다. 순수한 가상 메소드를 가진 클래스로부터 객체를 인스턴스화하려고하는 컴파일 에러가있다.

어떻게하면됩니까? - 각 유형에 대해 특정 생성자를 지정해야합니까? 그냥 핵심으로 복사하는거야? 아니면 RTTI를 통과해야합니까? 나는보다 더 나은 방법이 희망하는 2

편집 mergeFn가 초기화 (및 사용)됩니다 방법을 보여줍니다 :

std::unique_ptr<detail::DuplicateFn> foo; 
foo.reset(new detail::MergeFn(this, &Other, DuplicateFns.at(HandleDuplicate))); 

DuplicateFns 기능으로 사용자 입력 (문자열)로 변환하는 데 도움이되는지도이다 -pointers. - 지금 그대로 또는 DuplicateFn에서 서브 타입의 객체 (포인터 타입이 DuplicateFn *입니다)에 대한 포인터는

이 다음 콜백 방법 하나에 두 그루의 나무를 결합

ProjectTree.combine_if(tree, &SimilarTreeValue, foo.get()); 

로 사용됩니다 - SimilarTreeValue가 true를 돌려주는 경우 엔트리는 복제 된 것으로 간주됩니다. 엔트리가 잎이라면 세 번째 매개 변수가 호출됩니다 - 우리가 말하는 Functor입니다.

답변

-1

사용자 정의 소멸자를 취하여 빈 함수를 전달하는 shared_ptr의 생성자를 사용할 수 있습니다. 그래서 예를 들면.

MergeFn(GMProject const * Out, 
     GMProject const * In, 
     std::shared_ptr<DuplicateFn> f) /* ... */ 

두 번째 옵션은 clone() 기능을 전체 클래스 계층 구조를 부여하는 것입니다

void dontDelete(DuplicateFn *pFn) { 
    // Do nothing! 
    } 

class MergeFn : public DuplicateFn { 
public: 
    MergeFn() : FallBack(new SkipFn()) 
    { 
    } 

    MergeFn(GMProject const* Out, GMProject const* In, DuplicateFn* f) 
     : DuplicateFn(Out, In), FallBack(f, dontDelete) 
    { 
    } 

    virtual void operator() (GMProject::pTree& tOut, const GMProject::pTree& tIn) const { 
     if (!GMProject::isMergeable(tOut.GetName())) { 
      (*FallBack)(tOut, tIn); //virtual table resolves this to the correct class 
     } else { 
     } 
    } 

private: 
    std::shared_ptr<DuplicateFn> FallBack; 
}; 
+0

"_You 사용자 정의 소멸자 소요 shared_ptr의 생성자를 사용하고 it._가 비어있는 기능을 전달할 수 있습니다 "나는이 글을 읽을 때마다, 내 생각 :

당신은 복제 기능을 필요 싸구려 트릭을 가진 디자인 문제에서 벗어나지 못할 것 "이라고 말했다. 이것은 또 다른 예입니다. – curiousguy

1

(내보기에) 가장 쉬운 솔루션은 이미 공유 포인터를 요구하는 생성자의 서명을 변경하는 것입니다 예 : FallBack(f->clone()).

개인적으로 나는 첫 번째 버전으로 가고 고유 포인터로 공유 포인터를 교체하는 것이 타당하지 않은지 여부도 확인합니다.

만 펑 f 슬라이스합니다
+0

"_ 공유 포인터를 고유 포인터로 바꾸십시오 ._"이유가 무엇입니까? – curiousguy

+0

@curiousguy :'unique_ptr'은 훨씬 가벼운 (동적 할당이없고 가상 디스패치가 없습니다) 것입니다. 정말로 * share * 소유권이 필요한 경우에만'shared_ptr'을 사용하십시오. –

+0

"소유권을 정말로 공유해야하는 경우 shared_ptr 만 사용하십시오 ._"여기에 발신자와 수신자가 적어도 2 명이 있습니다. 'unique_ptr'유형의 함수 인수는 소유권 이전을 의미합니다. 발신자가 여전히 소유권을 원한다면 어떻게해야합니까? – curiousguy

0

new DuplicateFn(f)

."려고

#include <typeinfo> 
#include <cassert> 

template <class T> 
// runtime checked clone function 
// T::do_clone() must be accessible to checked_clone 
T *checked_clone (const T* that) { 
    T *p = that->do_clone(); 
    assert (typeid (*p) == typeid (*that)); 
    return p; 
} 

// clone for an abstract class 
#define IMPLEMENT_CLONE_ABSTRACT(Class) \ 
    friend Class *checked_clone<Class> (const Class* that); \ 
\ 
public: \ 
    Class *clone_naked() const { \ 
     return checked_clone (this); \ 
    } \ 
    unique_ptr<Class> clone_unique() const { \ 
     return unique_ptr<Class> (checked_clone (this)); \ 
    } \  \ 
private: \ 
    virtual Class *do_clone() const = 0; \ 
/* end of IMPLEMENT_CLONE_ABSTRACT */ 

class Base { 
    IMPLEMENT_CLONE_ABSTRACT(Base) 
}; 

// clone for a concrete class 
#define IMPLEMENT_CLONE_CONCRETE(Class) \ 
    friend Class *checked_clone<Class> (const Class* that); \ 
\ 
public: \ 
    Class *clone_naked() const { \ 
     return checked_clone (this); \ 
    } \ 
    unique_ptr<Class> clone_unique() const { \ 
     return unique_ptr<Class> (checked_clone (this)); \ 
    } \  \ 
\ 
private: \ 
    virtual Class *do_clone() const { \ 
     return new Class (*this); \ 
    } \ 
/* end of IMPLEMENT_CLONE_CONCRETE */ 

class Derived : public Base { 
    IMPLEMENT_CLONE_CONCRETE(Derived) 
};