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 0OPTION 1そうではないので、その理由を理解したいと思います。

を使用OPTION 0すると、main呼び出し時d.set(x)にコンパイラーはとの間Derived<T>::set(const T& source)で選択できます。Derived<T>::set(const Base<T>& source)もちろん、T x彼はを選択しDerived<T>::set(const T& source)ます。

を使用すると、を呼び出すOPTION 1ときに、コンパイラにはとのどちらかを選択できると思います。maind.set(x)Base<T>::set(const T& source)Derived<T>::set(const Base<T>& source)

Base<T>::set(const T& source)ただし、コンパイラ(ここではGCC 4.6.3)は、を選択する代わりに、暗黙的にに変換xしてBase<T>を呼び出しますDerived<T>::set(const Base<T>& source)

正常ですか?

そして、(コンストラクターを変更せずに)それを回避するための一般的な手法(存在する場合)はOPTION 0OPTION 1ですか?

4

1 に答える 1

4

派生クラスの基本クラスから関数をオーバーロードする場合、基本クラス関数は非表示になり、using宣言が使用されない限り、オーバーロード解決によって選択されることはありません。つまり、コンパイラが選択できるようにするには、をBase<T>::set(const T&)追加します

using Base<T>::set;

派生クラスで。

于 2012-12-09T06:54:38.697 に答える