C++ 模板类继承
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10758686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Template class inheritance
提问by Vincent
I have a problem with the following piece of code (it is a very simplified example that reproduce the error in my program) :
我对以下代码段有问题(这是一个非常简化的示例,可重现我的程序中的错误):
#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;
}
And the error is the following :
错误如下:
error: cannot convert 'const CDerived<double>' to 'int' in initialization
How to solve that ? (with a preference for modifications in the base class and not in the derived class, and if possible no use of virtuality)
如何解决?(优先在基类而不是派生类中进行修改,如果可能,不使用虚拟性)
Thank you very much
非常感谢
EDIT :
If I replace the concerned line with : CDerived<int> di(CBase<int>(CBase<double>(dd1)));
it works but it is not very practical...
编辑:如果我将相关行替换为:CDerived<int> di(CBase<int>(CBase<double>(dd1)));
它可以工作,但不是很实用......
EDIT : Seems to be solved by that :
编辑:似乎可以通过以下方式解决:
template <class T2> CDerived(const CDerived<T2> &x) : CBase<T>(static_cast<const CBase<T2>&>(x)) {;}
回答by Nawaz
CDerived<int> di(dd1); // <- The problem is here
This invokes the first constructor of CDerived
, and so T2
is inferred as CDerived<double>
which is the type of dd1
. Then, dd1
becomes x
in the constructor; x
which is CDerived<double>
, gets passed to the base class constructor which accepts int
(which is the value of the type argument T
to CDerived
class template). Hence the error, as CDerived<double>
cannot be converted into int
. Note that T
of CBase
is int
.
这会调用 的第一个构造函数CDerived
,因此T2
推断为CDerived<double>
的类型dd1
。然后,在构造函数中dd1
变成x
;x
其是CDerived<double>
,被传递给基类构造函数,它接受int
(这是类型参数的值T
,以CDerived
类模板)。因此错误, asCDerived<double>
不能转换为int
. 注意T
的CBase
是int
。
See it as:
将其视为:
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
If you want to make your code work, then do this:
如果您想让代码正常工作,请执行以下操作:
- First derive publiclyinstead of privately.
- Add another constructor taking
CDerived<T2>
as parameter.
- 首先公开而不是私下派生。
- 添加另一个
CDerived<T2>
作为参数的构造函数。
So you need to so this:
所以你需要这样做:
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() {;}
};
It should work now : online demo
现在应该可以使用了:在线演示
回答by Hans Z
Try making another constructor that takes a generic object in your base class and assigns the value using dynamic casting.
尝试创建另一个构造函数,它在您的基类中接受一个通用对象并使用动态转换分配值。
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;
}
}
Note: This might be considered poor style. Dynamic casting is more expensive during runtime than using virtual
and overloads, so consider refactoring your code.
注意:这可能被认为是糟糕的风格。动态转换在运行时比 usingvirtual
和重载更昂贵,因此请考虑重构您的代码。