模板类继承

时间:2012-05-25 17:14:16

标签: c++ templates inheritance

我遇到以下代码问题(这是一个非常简单的示例,可以在我的程序中重现错误):

#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;
}

错误如下:

error: cannot convert 'const CDerived<double>' to 'int' in initialization

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

非常感谢

编辑: 如果我将相关的行替换为:CDerived<int> di(CBase<int>(CBase<double>(dd1)));它可以工作,但它不太实用......

编辑:似乎有待解决:

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

2 个答案:

答案 0 :(得分:5)

CDerived<int> di(dd1); // <- The problem is here

这将调用CDerived的第一个构造函数,因此T2被推断为CDerived<double>,这是dd1的类型。然后,dd1在构造函数中变为x; x CDerived<double>被传递给基类构造函数,该构造函数接受int(类型参数TCDerived类模板的值) 。因此错误,因为CDerived<double>无法转换为int。请注意T的{​​{1}}为CBase

将其视为:

int

如果您想让代码正常工作,请执行以下操作:

  1. 首先公开 而不是私下
  2. 添加另一个以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 为参数的构造函数。
  3. 所以你需要这样:

    CDerived<T2>

    现在应该可以使用:online demo

答案 1 :(得分:0)

尝试创建另一个构造函数,该构造函数在基类中获取泛型对象,并使用动态强制转换赋值。

template <class T2> CBase (const Object &x) : _var() {
    try {
        const CBase<T2> &x_casted = dynamic_cast<const CBase<T2> &> (x);
        _var = x_casted.var();
    }
    catch {
        std::cerr << "Object not of type CBase" << std::endl; 
    }
}

注意:这可能被认为是不好的风格。动态转换在运行时比使用virtual和重载更昂贵,因此请考虑重构代码。