我遇到以下代码问题(这是一个非常简单的示例,可以在我的程序中重现错误):
#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)) {;}
答案 0 :(得分:5)
CDerived<int> di(dd1); // <- The problem is here
这将调用CDerived
的第一个构造函数,因此T2
被推断为CDerived<double>
,这是dd1
的类型。然后,dd1
在构造函数中变为x
; x
CDerived<double>
被传递给基类构造函数,该构造函数接受int
(类型参数T
到CDerived
类模板的值) 。因此错误,因为CDerived<double>
无法转换为int
。请注意T
的{{1}}为CBase
。
将其视为:
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
为参数的构造函数。所以你需要这样:
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
和重载更昂贵,因此请考虑重构代码。