2011-08-23 2 views
5

GSL의 일부분에 C++ 래퍼를 작성하고 다음 퍼즐을 찾습니다. 다음과 같이 (의 필수 요소로 감소) 코드는 다음과 같습니다슈퍼 클래스 (값 전달)로 인해 오버로드 된 생성자의 모호한 호출

#include <stdlib.h> 
    struct gsl_vector_view {}; 

    class Vector : protected gsl_vector_view { 
      public: 
      Vector (const Vector& original); 
      Vector (const gsl_vector_view view); 
    }; 

    class AutoVector : public Vector { 
      public: 
      explicit AutoVector (const size_t dims); 
    }; 

    void useVector (const Vector b) {} 

    void test() { 
      const AutoVector ov(2); 
      useVector(ov); 
    } 

나는 당황 스럽네요

 In function ‘void test()’: 
    19: error: call of overloaded ‘Vector(const AutoVector&)’ is ambiguous 
    7: note: candidates are: Vector::Vector(gsl_vector_view) 
    6: note:     Vector::Vector(const Vector&) 
    19: error: initializing argument 1 of ‘void useVector(Vector)’ 

을 GCC 4.4.5 g ++ -c v.cpp 를 사용하여 컴파일하지만 양보하지 않습니다 그 protected gsl_vector_view 기본 클래스는 useVector (Vector)를 호출하여 고려됩니다. 나는 useVector가 "The C++ Programming Language", 3 번째 e. p의 말로 "일반 대중"에 속한다고 생각했을 것이다. 405에 의해 보호되고 따라서 보호 된 정보에 대한 액세스 권한이 없으므로이 정보로 혼동 될 수 없습니다. 가 나는 (중 이해가 안 정직하게, 그리고,) 내가 모르는 무엇

explicit Vector (const gsl_vector_view view); 

로 생성자를 선언함으로써 모호성 제거 할 수 있다는 것을 알고 때 오버로드 된 호출의 모호성이 사라지고 있다는 것입니다

Vector (const gsl_vector_view& view); 

으로 인수를 전달하십시오. (나는 어쨌든 적절한 방법을 생각합니다).

+0

+1,'protected' 상속과는 아무런 관련이 없습니다. 그래서 질문을 다시 포맷하십시오. – iammilind

+0

btw. useVector에서 참조를 선언 할 때 모호성이 사라집니다. – PlasmaHH

답변

4

오버로드 확인은 액세스 검사 전에 수행되므로 보호 된 기본 클래스 구성원도 고려됩니다.

오버로드 해상도는 표준 13.3 장에 설명되어 있습니다. 내 해석에 따르면 const AutoVector ovVector (const Vector& original);으로 바인딩하는 것은 사용자 정의 변환, 유도 - 기반 변환 ([13.3.3.1.4/1]) 종류입니다. Vector (const gsl_vector_view view);의 경우 사용자 정의 변환이 뒤에 오는 왼쪽 값과 오른쪽 값 변환이므로 변환 시퀀스도 사용자 정의 변환입니다. 따라서 두 전환 시퀀스가 ​​동일하다고 간주되고 아무 것도 다른 것보다 좋지 않으므로 모호성이 발생합니다. 만약 Vector (const gsl_vector_view& view);로 변경하는 경우의 ctor

이제 두 변환 사용자 정의 변환 (유도 투베이스 전환) 다음 좌변 투 변환 값이다. 그 두 가지는 주문할 수 있으며 ([13.3.3.2/4]) const Vector&으로의 변환이 더 잘 고려되므로 애매 모호하지 않습니다.

1

질문은 protected 상속 또는 생성자와 관련이 없습니다. 이 문제는 일반 함수 호출에서도 지속됩니다 (상속과 함께).

모든 오버로드 버전에서 참조로 전달할 때 가장 가까운 기본 클래스가 선택됩니다 (가장 가까운 기본 클래스가 1 개 이상있는 경우 가장 인접한 기본 클래스가 선택됩니다).

전달 값의 경우 모든 함수가 똑같이 좋은 후보로 간주됩니다. 따라서이 컴파일 오류가 발생합니다. 귀하의 질문에 다소 일치하는 표준 견적의 작은 통로가 있습니다.

§ 13.3.1 (5)
... ref-qualifier없이 선언 된 비 정적 멤버 함수의 경우 추가 규칙이 적용됩니다. - 암시 적 개체 매개 변수가 const 한정이 아니더라도 다른 모든 측면에서 r 값을 매개 변수에 바인딩 할 수 있습니다. 인수는 암시 적 객체 매개 변수 유형으로 변환 된 일 수 있습니다.