2012-12-09 1 views
1

는 테스트 코드입니다 :기능 과부하, 상속 및 암시 적 생성자 : 이상한 우선 순위가 여기에

#include <iostream> 
#define OPTION 1 

template<typename T> 
class Base 
{ 
    public: 
     Base() : _x() 
     {std::cout<<"Base()"<<std::endl;} 

     Base(const T& source) : _x(source) 
     {std::cout<<"Base(const T& source)"<<std::endl;} 

     Base(const Base<T>& source) : _x(source.x) 
     {std::cout<<"Base(const Base<T>& source)"<<std::endl;} 

    public: 
     inline void set(const T& source) 
     {std::cout<<"Base::set(const T& source)"<<std::endl; 
     this->_x = source;} 

     inline T get() const 
     {std::cout<<"Base::get(const T& source)"<<std::endl; return _x;} 

    protected: 
     T _x; 
}; 

template<typename T> 
class Derived : public Base<T> 
{ 
    public: 
     Derived() : Base<T>() 
     {std::cout<<"Derived()"<<std::endl;} 

     Derived(const T& source) : Base<T>(source) 
     {std::cout<<"Derived(const T& source)"<<std::endl;} 

     Derived(const Derived<T>& source) : Base<T>(source) 
     {std::cout<<"Derived(const Derived<T>& source)"<<std::endl;} 

    public: 
     #if OPTION == 0 
     inline void set(const T& source) 
     {std::cout<<"Derived::set(const T& source)"<<std::endl; 
     this->_x = source;} 
     #endif 

     inline void set(const Base<T>& source) 
     {std::cout<<"Derived::set(const Base<T>& source)"<<std::endl; 
     this->_x = source.get();} 
}; 

int main(int argc, char* argv[]) 
{ 
    Derived<double> d; 
    double x = 4.5; 
    d.set(x); 
    return 0; 
} 
OPTION 0를 들어

OPTION 1 동등한 것하지만 그들은하지 않습니다 나는 이유를 이해하고 싶습니다. OPTION 0

main 호출은 컴파일러가 Derived<T>::set(const T& source)Derived<T>::set(const Base<T>& source) 물론, T x 위해 그가 Derived<T>::set(const T& source)를 선택 사이의 선택의 여지가있다 d.set(x) 때. main 전화 d.set(x), 나는 컴파일러가 Base<T>::set(const T& source)Derived<T>::set(const Base<T>& source) 사이의 선택의 여지가 있다고 생각 OPTION 1와 지금

.

대신 Base<T>::set(const T& source)을 선택하는 대신 컴파일러 (여기 GCC 4.6.3)는 x을 암시 적으로 Base<T>으로 변환하고 Derived<T>::set(const Base<T>& source)을 호출합니다.

정상입니까?

OPTION 0OPTION 1을 동등하게하기 위해 (생성자를 변경하지 않고) 일반적인 기술 (있을 경우)이 무엇입니까?

+0

실제로 스트림을 플러시하지 않는다면 [std :: endl' 사용을 중지하십시오] (http://kuhllib.com/2012/01/14/stop-excessive-use-of-stdendl/)해야합니다. –

+0

물론 나는 공연이 필요할 때 std :: endl을 사용하지 않는다. 그러나 여기에는 나의 요점이 아니다. 하지만 당신 말이 맞아요. (그럼에도 불구하고, 로그 파일과 같은 것들에 대해서는 std :: endl이 "\ n"보다 더 편리 할 것입니다.) – Vincent

답변

4

파생 클래스의 기본 클래스에서 함수를 오버로드하면 기본 클래스 함수가 ​​숨겨져 using 선언을 사용하지 않으면 오버로드 확인에 의해 선택되지 않습니다. 즉, 컴파일러가 Base<T>::set(const T&)를 선택할 수 있도록하기 위해, 당신은 당신의 파생 클래스에서

using Base<T>::set; 

을 추가 한 것입니다.

+0

이 구문은 C++ 11 또는 C++ 03입니까? (get() 메서드가 해결됨) – Vincent

+0

C++ 98에서 소개 된 선언을 사용한다고 생각합니다. –

+0

템플릿 함수로도 작업하고 있습니까? (이 경우 사용 행에 템플릿 매개 변수를 지정해야합니까?) – Vincent