2014-04-27 1 views
2

당신이 라이브러리의 내부 기본 클래스가 있다고 가정 기본 유형에 저장된 특정 파생 된 유형의 인스턴스 찾기 :벡터, 모든

class A {}; 

및 파생 클래스

class B: public A {}; 
class C: public A {}; 

은 이제 BC의 인스턴스는 표준에 저장됩니다 : 벡터를 boost::shared_ptr<A>의 :

std::vector<boost::shared_ptr<A> > A_vec; 
A_vec.push_back(boost::shared_ptr<B>(new B())); 
A_vec.push_back(boost::shared_ptr<C>(new C())); 

BC의 인스턴스를 추가하는 것은 사용자가 수행하므로 추가 될 순서를 미리 결정할 방법이 없습니다.

그러나, 라이브러리의 내부 BC에 특정 작업을 수행 할 필요가있을 수 있으므로 기본 클래스에 대한 포인터는 BC에 주조 될 필요가있다.

당연히 "시행 착오"전환을 수행 할 수 있습니다. 즉, 던지지 않는 전환을 찾을 때까지 BC (및 기타 기본 클래스의 파생물)으로 캐스팅을 시도 할 수 있습니다. 그러나이 방법은 매우 조잡하고 오류가 발생하기 쉽고 좀 더 우아하고 (그리고 성능이 좋은) 방법을 찾고 있습니다.

저는 C++ 98에서도 작동 할 수있는 솔루션을 찾고 있지만 기능을 향상시킬 수 있습니다.

아이디어가 있으십니까?


편집 :

오케이, 지금까지 모든 답변에 대한 감사합니다!

유스 케이스에 대해 더 자세히 설명하고 싶습니다. 이 모든 것은 파라 메트릭 최적화와 관련하여 발생합니다. (예를 들어, "제약 정수", "구속 더블", "부울"등 "이중 구속") 초기 자신의 유형, 즉

  • 매개 변수를 지정 :

    사용자에 의해 최적화 문제를 정의 소정의 매개 변수, 하나 개 이상의 평가 (큰 값)가 부여하는 평가 함수가

다른 최적화 알고리즘이 그들의 파라미터를 포함하여, 문제 정의 행동 설정 지정

  • 값.

    일반적인 경우에 미리 정의 된 매개 변수 개체가 많이 있지만 사용자는 내 기본 클래스 중 하나에서 파생하여 자체 매개 변수 개체를 만들 수도 있습니다. 그래서 라이브러리 관점에서 볼 때 매개 변수 객체가 주어진 (기본 클래스) API를 준수해야한다는 것 외에도 매개 변수 객체에 대해 많이 생각할 수 없습니다.

    문제 정의는 std :: vector 인터페이스가있는 기본 클래스에서 파생 된 사용자 정의 C++ 클래스입니다. 사용자는 자신의 (미리 정의되거나 자체 성장 된) 매개 변수 객체를 추가하고 적합성 기능에 과부하를줍니다.(파생 매개 변수 객체는 그 값에 대한 액세스 기능을 제공하기 위해 필요로하는, 심지어 집에서 재배 한 매개 변수 객체에 대해, 일반적으로 오케이) 파라미터 객체에

    액세스는 최적화 알고리즘 내에서

    • 을 발생할 수 있습니다. 사용자가 제공 한 피트니스 함수 내에서
    • (보통 오케이, 사용자가 컬렉션에있는 매개 변수 개체를 발견하고 그 가치를 쉽게 액세스 할 수있는 위치를 알고로)

    이 잘 작동합니다. 그러나 사용자가 제 3자가 매개 변수 구조를 제공하고있다

  • 자신의 집에서 재배 한 매개 변수 유형의 특성에 액세스하려고

    • 특별한 경우가있을 수 있습니다

      는 (이 오픈 소스 라이브러리, 다른 사람이다 특정 최적화 문제에 대한 코드를 추가 할 수 있습니다.)

    • 최적화 문제의 일부로 매개 변수 구조 (즉, 매개 변수가있는 위치)가 수정 될 수 있습니다. 예 : 신경망 아키텍처의 학습

    이러한 상황에서 기본 유형 모음 내부에서 지정된 파생 유형의 모든 매개 변수 객체에 액세스하는 쉬운 방법을 갖는 것이 좋습니다.

    이미 템플릿이있는 "conversion_iterator"가 있습니다. 기본 객체의 벡터를 반복하고 원하는 대상 유형을 준수하지 않는 객체는 건너 뜁니다. 그러나 이것은 "시행 착오"전환 (즉, 변환 된 스마트 포인터가 NULL인지 여부를 확인)을 기반으로합니다. 이는 매우 비현실적이며 오류가 발생하기 쉽습니다.

    더 나은 솔루션을 갖고 싶습니다.

    NB : 최적화 라이브러리는 주어진 매개 변수 집합에 대한 평가 단계가 임의로 길어질 수있는 (일반적으로 초, 아마도 몇 시간 또는 그 이상) 유스 케이스에서 타겟팅됩니다. 따라서 매개 변수 유형에 대한 액세스 속도는 그리 중요하지 않습니다. 하지만 안정성과 유지 보수성은 ...

  • +3

    '가상'메소드를 제외하고, 당신은 의미합니까? – delnan

    답변

    5

    캐스팅하고 성공 여부를 확인하는 것보다 나은 일반적인 해결책은 없습니다. 일 수 있으며 동적으로 typeid을 얻고이를 모든 유형과 차례로 비교할 수는 있지만 실제로는 동일한 양입니다.

    근본적으로, 당신이해야 할 일은 디자인 문제에 대한 힌트입니다. 기본 클래스의 전체 목적은 아이들을 부모처럼 다루는 것입니다. 이것이 필요한 경우에는 특정 상황이 있으며,이 경우 visitor을 사용하여 전달할 수 있습니다.

    +0

    RTTI가 활성화 된 경우에만 작동합니다. 두 번째 요점은 100 % 정확합니다, IMO. – KitsuneYMG

    +3

    RTTI가 활성화되어 있지 않으면 실제로 C++이 아닙니다. – aschepler

    +1

    "근본적으로, 당신이 이것을 할 필요가 디자인 문제를 암시합니다"- 완전히 이것! –

    2

    가능하면 A 클래스에 가상 메서드를 추가하여 BC의 특정 작업을 수행하십시오.

    그럴 수 없거나 적절하지 않은 경우에는 dynamic_cast의 포인터 양식을 사용하십시오. 따라서 예외는 없습니다. B와 C의

    for (boost::shared_ptr<A> a : A_vec) 
    { 
        if (B* b = dynamic_cast<B*>(a.get())) 
        { 
         b->do_something(); 
        } 
        else if (C* c = dynamic_cast<C*>(a.get())) 
        { 
         something_else(*c); 
        } 
    } 
    
    1

    추가 인스턴스는 사용자에 의해 수행되며, 미리 이들이 첨가되는 순서를 결정하는 방법이 없다.

    좋아, 그럼 두 개의 다른 용기에 넣으시겠습니까?

    std::vector<boost::shared_ptr<A> > A_vec; 
    std::vector<boost::shared_ptr<B> > B_vec; 
    std::vector<boost::shared_ptr<C> > C_vec; 
    
    void add(B * p) 
    { 
        B_vec.push_back(boost::shared_ptr<B>(p)); 
        A_vec.push_back(b.back()); 
    } 
    
    void add(C * p) 
    { 
        C_vec.push_back(boost::shared_ptr<C>(p)); 
        A_vec.push_back(c.back()); 
    } 
    

    그런 다음 Bs 또는 C를 반복하여 내 마음에 넣을 수 있습니다.

    0

    특정 개체의 형식을 반환하는 기본 클래스 (예 : TypeOf())에 메서드를 구현하는 것이 좋습니다. 파생 된 유형에서 구현할 수 있도록 해당 메소드를 가상 및 추상으로 정의해야합니다. 유형 자체는 각 유형 (예 : 클래스)에 대한 열거 형을 정의 할 수 있습니다.

    enum class ClassType { ClassA, ClassB, ClassC }; 
    
    0

    이 대답은 관심 있습니다 Generating an interface without virtual functions?

    를이 방법을 보여줍니다 모두

    • 변형 한 컬렉션/방문자
    • 별도의 컬렉션 승 접근,

    a (Fred와 Konrad, 특히). 후자는 반복에 더 효율적이며 전자는 순결하고 유지 보수가 잘 될 수 있습니다. 사용 패턴에 따라 더 효율적 일 수도 있습니다.