7
class messageA { 
}; 

class messageB { 
}; 

template<class T> 
class queue { 
public: 
    virtual ~queue() {} 
    void submit(T& x) {} 
}; 

class A : public queue<messageA>, public queue<messageB> 
{ 
}; 

int main() 
{ 
    A aa; 
    aa.submit(messageA()); 
    aa.submit(messageB()); 
} 

클래스 A는 messageA와 messageB 객체를 받아들이는 2 개의 오버로드 된 submit 함수를 포함하기 때문에 위의 코드는 괜찮을 것이라고 생각합니다.다중 상속 템플릿 클래스

내가 모호한 존재 이유를 알고있다 :

그러나, 컴파일러는 나에게 다음과 같은 오류 준다? 첫 번째 제출 요청에 대해 messageA 버전을 호출하고 싶습니다. 두 번째 제출 통화의 경우 messageB 버전을 호출하고 싶습니까?


------ Build started: Project: main, Configuration: Release Win32 ------ 
Compiling... 
main.cpp 
.\main.cpp(21) : error C2385: ambiguous access of 'submit' 
     could be the 'submit' in base 'queue<messageA>' 
     or could be the 'submit' in base 'queue<messageB>' 
.\main.cpp(21) : error C3861: 'submit': identifier not found 
.\main.cpp(22) : error C2385: ambiguous access of 'submit' 
     could be the 'submit' in base 'queue<messageA>' 
     or could be the 'submit' in base 'queue<messageB>' 
.\main.cpp(22) : error C2664: 'queue<T>::submit' : cannot convert parameter 1 from 'messageB' to 'messageA &' 
     with 
     [ 
      T=messageA 
     ] 
.\main.cpp(22) : error C3861: 'submit': identifier not found 
+0

'messageA'에서'messageA &'로 암시 적으로 변환하는 것은 표준 C++가 아닙니다. 비 const 참조는 lvalue (http://msdn.microsoft.com/en-us/library/186yxbac(VS.80).aspx)에만 바인딩 할 수 있습니다. 'submit()'함수는'T &'대신'const T &'를 받아 들여야합니다. –

답변

11

지금은 더 컴파일러가 없다,하지만 난 하나 상속이 다른 숨길 수있을 것 같아요 : 컴파일러는 바로 기호를 찾을 Koenig Lookup를 사용을하고, 내가 정확히 기억한다면, 컴파일러 일단 적당한을 찾아 심볼 (즉, "submit"이라는 메소드)를 사용하면 부모 및/또는 바깥 범위의 다른 검색을 중지합니다.

이 경우에는 상속하는 클래스 둘 다 심볼을 검색하지만 정확한 컴파일러 (Visual C++ 2003? 2008? 2010?)가 없으면 훨씬 더 추측 할 수 없습니다.

컴파일러가 두 심볼을 모두 찾았지만 호출 할 것인지 결정할 수없는 경우가 있습니다 (심볼 해상도의 순간에 컴파일러는 정확한 프로토 타입이 아닌 심볼 이름 만 신경 씁니다). 나는이 마지막 설명이 옳은 것이라고 생각한다. 파생 클래스에서 문을 사용하여 추가

시도 :

class A : public queue<messageA>, public queue<messageB> 
{ 
    using queue<messageA>::submit ; 
    using queue<messageB>::submit ; 
} ; 

가져올 모두는 A 클래스 범위에서 메서드를 직접 제출.

제출 메서드가 메시지를 비 const 참조로 사용하고 있으며 생성자에서 메시지 매개 변수가 임시 메시지 (및 const r 값)임을 유의하십시오.

다시을 writting로 주를 : 컴파일 도움이 될 수

int main() 
{ 
    A aa; 
    messageA mA ; 
    messageA mB ; 
    aa.submit(mA); 
    aa.submit(mB); 
} 

(이 라인 (22)에 컴파일러 오류를 설명 할 수있다).

또는 제출하지 않은 메소드 대신 const 참조를 허용하도록 제출 메소드의 프로토 타입을 변경할 수 있습니다.

참고 : 아직도 컴파일러 않고, 그래서

+0

"_I 상속 하나가 숨길 수 있습니다." "_ 컴파일러는 Koenig Lookup_을 사용합니다."아니오, 그렇지 않습니다. "_ 컴파일러는 두 기호를 모두 찾았지 만 어느 것을 호출할지 결정할 수는 없습니다." "예. – curiousguy

+0

"_temporaries (따라서 const r 값) ._"아니요, 임시 변수는 ** 상수가 아닙니다 ** 상수입니다. – curiousguy

1
Something* smth1 = ((Base<Something> *)d)->createBase<Something>(); 

... 뇌 - 디버깅 - P ... 코드를에 위의 코드를 시도하는 것은 잘 작동합니다.

+0

"'((Base *) d)"매우 추악하고 매우 위험합니다.이 C 스타일의 캐스트로 심각한 유형 문제를 숨길 수 있습니다. OTOH,이'Base & dBase = * d; dBase.createBase ();'은 안전합니다. – curiousguy