函数重载,继承和隐式构造函数:奇怪的优先级

时间:2012-12-09 06:30:14

标签: c++ inheritance constructor c++11 overloading

这是一个测试代码:

#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,当main调用d.set(x)时,我认为编译器可以在Base<T>::set(const T& source)Derived<T>::set(const Base<T>& source)之间进行选择。

但是,编译器(此处为GCC 4.6.3)不是选择Base<T>::set(const T& source),而是隐含地将x转换为Base<T>并调用Derived<T>::set(const Base<T>& source)

这是正常的吗?

为了避免这种情况(不改变构造函数)以使OPTION 0OPTION 1具有等效性,常见的技术(如果存在)是什么?

1 个答案:

答案 0 :(得分:4)

当从派生类中的基类重载函数时,除非使用using声明,否则基类函数将被隐藏并且永远不会被重载决策选择。也就是说,为了让编译器选择Base<T>::set(const T&),你添加了

using Base<T>::set;

在派生类中。