模板类继承

Vin*_*ent 4 c++ inheritance templates

我有一个问题与下面的代码(这是一个非常简单的例子,重现我的程序中的错误):

#include <iostream>

using namespace std;

template<class T> class CBase
{
    public:
        template <class T2> CBase(const T2 &x) : _var(x) {;}
        template <class T2> CBase (const CBase<T2> &x) {_var = x.var();}
        ~CBase() {;}
        T var() const {return _var;}
    protected:
        T _var;
};

template<class T> class CDerived : public CBase<T>
{
    public:
        template <class T2> CDerived(const T2 &x) : CBase<T>(x) {;}
        template <class T2> CDerived (const CBase<T2> &x) : CBase<T>(x) {;}
        ~CDerived() {;}
};

int main()
{
    CBase<double> bd(3);
    CBase<int> bi(bd); // <- No problem
    CDerived<double> dd1(3);
    CDerived<double> dd2(dd1);
    CDerived<int> di(dd1); // <- The problem is here
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误如下:

error: cannot convert 'const CDerived<double>' to 'int' in initialization
Run Code Online (Sandbox Code Playgroud)

怎么解决?(优先选择基类而不是派生类,如果可能,不使用虚拟)

非常感谢你

编辑:如果我更换相关的行:CDerived<int> di(CBase<int>(CBase<double>(dd1)));它的工作原理,但它不是很实用...

编辑:似乎有待解决:

template <class T2> CDerived(const CDerived<T2> &x) : CBase<T>(static_cast<const CBase<T2>&>(x)) {;}
Run Code Online (Sandbox Code Playgroud)

Naw*_*waz 5

CDerived<int> di(dd1); // <- The problem is here
Run Code Online (Sandbox Code Playgroud)

这将调用第一个构造函数CDerived,因此T2推断出CDerived<double>它的类型dd1.然后,dd1成为x构造函数; x其是CDerived<double>,被传递给基类构造函数,它接受int(这是类型参数的值T,以CDerived类模板).因此错误,因为CDerived<double>无法转换成int.注意TCBase就是int.

看作是:

CDerived<int> di(dd1); // <- The problem is here
          ^       ^
          |       |
          |       this helps compiler to deduce T2 as double
          |
          this is T of the CDerived as well as of CBase
Run Code Online (Sandbox Code Playgroud)

如果要使代码正常工作,请执行以下操作:

  1. 首先是公开而非私下.
  2. 添加另一个构造函数CDerived<T2>作为参数.

所以你需要这样:

template<class T> class CDerived : public CBase<T>  //derived publicly
{
    public:
        template <class T2> CDerived(const T2 &x) : CBase<T>(x) {;}

        //add this constructor
        template <class T2> CDerived(const CDerived<T2> &x) : CBase<T>(x.var()) {;}

        template <class T2> CDerived (const CBase<T2> &x) : CBase<T>(x) {;}
        ~CDerived() {;}
};
Run Code Online (Sandbox Code Playgroud)

它现在应该工作:在线演示