这是一个测试代码:
#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
调用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 0
和OPTION 1
具有等效性,常见的技术(如果存在)是什么?
答案 0 :(得分:4)
当从派生类中的基类重载函数时,除非使用using
声明,否则基类函数将被隐藏并且永远不会被重载决策选择。也就是说,为了让编译器选择Base<T>::set(const T&)
,你添加了
using Base<T>::set;
在派生类中。