2012-07-24 2 views
1

기본적으로 일부 알고리즘을 실행하는 템플릿이있는 클래스가 있으며이 알고리즘은 T 유형의 두 개체가 비슷한 유형을 정의하는 double을 반환하는 similarity(T t1, T t2) 함수를 필요로합니다. 이 유사 함수는 T가 정의 된대로 크게 달라 지므로이 클래스의 호출자는 유사 함수를 정의해야합니다. 함수 포인터가 순서대로 있다고 가정합니다. 그러나 함수 포인터를 함수에 저장하기 위해 어떻게 멤버 함수로 함수에 저장합니까?어떻게 함수 포인터에서 함수를 클래스의 멤버 함수로 저장합니까?

즉, 클래스의 생성자에 similarity(T t1, T t2)을 전달하고이를 클래스 전체의 멤버 함수로 호출 할 수 있습니다. 어떻게해야합니까? 감사합니다

+0

함수 포인터 외에도'가상'인터페이스 및/또는'std :: function' /'boost :: function' 명령이있을 수 있습니다. – Flexo

+0

다음은'std :: function'을 사용하지 않는 것입니다 : http://ideone.com/2A4Rc. 'std :: function'에 접근 할 수 있다면 훨씬 더 유연 해집니다. 이를 사용하여 객체의 멤버를 사용하려면'std :: bind'를 사용하여 객체를 바인드 할 수 있습니다. – chris

+0

알고리즘을 사용하여 코드에서 'similarity'의 특수화를 볼 수없는 이유는 무엇입니까? – juanchopanza

답변

2

런타임에 클래스에 멤버 함수를 추가 할 수 없습니다.

class MyClass { 
    typedef double (*similarity_fn_type)(T t1, T t2); 
    similarity_fn_type similarity_fn; 
    public: 
    MyClass(similarity_fn_type ptr) : similarity_fn(ptr) {} 
    double similarity(T t1, T t2) { 
     return similarity_fn(t1, t2); 
    } 
}; 

는 다른 방법으로, similarity_fn 멤버를 공개 할 수있다 :

당신은 함수 포인터를 통해 제공되는 함수를 호출하는 멤버 함수를 작성할 수 있습니다. 이것을 호출하는 구문은 멤버 함수처럼 보일 수 있지만 위대한 캡슐화로 간주하지 않을 수 있습니다.

+0

필자는 함수를 public으로 만들지 않을 것입니다. public으로 설정하면 외부 코드가 다른 함수로 변경되거나 다른 불쾌한 수정을 수행 할 수 있습니다. –

+0

@David : "위대한 캡슐화"의 한 가지 결과입니다. member는 non-const이며, 여기에 'MyClass'를 할당 할 수 있습니다.) 때로는 언어에 따라 캡슐화를 강요하기도하고 그렇지 않은 경우도 있습니다. 여기에는 (a) 모든 파이썬 프로그램, (b) 모든 C 구조체, (c) C++의 POD 구조체가 포함되지 않은 사례가 있으므로 많은 선례가 있습니다. –

+0

나는 그가 액세스 할 필요가없는 클래스의 다른 멤버들로부터 만 멤버 함수로 호출하기를 원한다는 것을 이해한다. 다른 예제들처럼, 파이썬 ... 뭐라 말할 수 있겠습니까? 많은 경우에 C 라이브러리는 평소보다 더 많은 캡슐화 수준을 제공합니다. C++ 접근법은 불투명 포인터를 사용합니다. 예, POD 유형은 캡슐화하지 않도록 특별히 설계되었습니다. :) 나는 그가 클래스 외부에서 함수를 호출하고 싶지는 않지만 내부적으로 만 믿고 있기 때문에 어쨌든 주석이있었습니다. –

0

나는 컬렉션을 반복하는 과정을 추상화하는 것과 비슷한 것을합니다. 나는 실제 검색 조건을 지정하는 술어를 사용

void MyClass::Copy(Class &destination, const Class &source, const std::function<bool (const Effect&)> &predicate) 
{ 
    for (size_t i = 0; i < Effect::Max; ++i) 
    { 
     const Effect *const pEffect = source.GetEffect(i); 
     if (predicate(*pEffect)) 
     { 
      // Do something 
     } 
    } 
} 

void MyClass::CopyInner(Class &destination, const Class &source) 
{ 
    this->Copy(destination, source, [](const Effect &effect) 
    { 
     return effect.IsInner(); 
    }); 
} 

: 이것은 일부 C++ 11 기능을 사용합니다. 생성자가 입력하는 기능을 허용하자

typedef double(*Similarity)(T, T); 
const Similarity similarity; 

:

+0

이것은'std :: function'을 사용하지 않고 전통적인'template '일 수도 있습니다. 그렇게하면 동적 할당이 필요 없습니다. –

+0

@ 존 : 'MyClass' 객체의 유형이 "술어"의 유형에 의존하도록하려는 경우 클래스 템플릿이 될 수 있습니다. –

+0

@SteveJessop : 그것은 또 다른 옵션이며 아마도 더 의미 론적으로 정확 합니다만 C++에서는별로 즐겁지가 않습니다. 기본 클래스를 만들거나 모든 'MyClass' 소비자를 템플릿으로 만들지 않고도 공통 인터페이스가 없습니다. –

0

적절한 유형의 const 함수 포인터 부재 정의

Class(Similarity f) : similarity(f) {} 

그런 다음 함수를 호출 호출과 같은 구문을 가지고 일반 회원 기능 :

frobnicate(similarity(foo, bar)); 

회원이 public 인 경우, const이기 때문에 회원님을 아래에서 변경할 수 없습니다.

1

더 깨끗하고 객체 지향적 인 방법이 있습니다. 그 중 하나는 Java가 Comparator 클래스와 비교를 재 구현할 수 있도록하는 것과 비슷한 기능을 가진 객체를 전달하는 것입니다. 이것은 similarity()의 각 구현에 대한 기본 클래스 (순수하게 가상이라는 함수가있는)와 하위 클래스의 생성을 의미합니다.

비교와 해시 함수를 구현할 때 C++ 11 솔루션이 더 유용 할 수 있습니다. 특수 함수 객체를 만드는 과정이 포함됩니다. 예를 들어 std::lessstd::hash을 참조하십시오.

+0

나는 downvote하지 않을 것이다, 그러나 나는 동의하지 않는다. 관용적 인 C++에서 가능한 경우 generic 프로그래밍 (정적 다형성)이 객체 지향 프로그래밍 (런타임 다형성)보다 선호됩니다. –

+0

나는 여기에서 우려를 이해한다. 자바에 대한 경험으로이 상황에서 피할 수있는 런타임 다형성에 대한 걱정을 덜어 줬습니다. –

+0

예,이 경우는 주로 스타일의 문제입니다. –

관련 문제