4

我对以下代码有疑问(这是一个非常简化的示例,可以在我的程序中重现错误):

#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)) {;}
4

2 回答 2

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

这会调用 的第一个构造函数CDerived,因此T2推断出CDerived<double>哪个是 的类型dd1。然后,dd1成为x构造函数;x也就是说CDerived<double>,被传递给接受的基类构造函数(这是类模板int的类型参数的值T) 。CDerived因此错误, asCDerived<double>不能转换为int. 请注意TCBaseint

将其视为:

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

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

  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() {;}
};

它现在应该可以工作了:在线演示

于 2012-05-25T17:21:31.403 回答
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和重载更昂贵,因此请考虑重构代码。

于 2012-05-25T17:33:33.047 回答