我有以下模板类, 我需要弄清楚如何在派生模板类之间实现转换运算符。
template<class T>
class Base
{
public:
Base () { }
template <class U>
operator Base<U>()
{
return Base<U> (v);
}
virtual double getV() = 0;
};
class D1: public Base<D1>
{
public:
D1(int j)
{
i = j;
}
double getV() const { return i; }
template <class U>
operator Base<U>()
{
return Base<U>(getV());
}
private:
int i;
};
class D2: public Base<D2>
{
public:
D2(int j)
{
i2 = j;
}
double getV() const { return i2; }
template <class U>
operator Base<U>()
{
return Base<U>(getV());
}
private:
int i2;
};
如何实现以下目标?
D1 d1(3);
D2 d2 = d1; //conversion from 'D1' to non-scalar type 'D2' requested
如果设计本身听起来还是应该做其他事情?
请让我知道你的想法
答案 0 :(得分:0)
很难说你想要做什么,但我认为你不能按照描述去做。
如果你真的想拥有一个通用接口,你需要声明一个包含你的代码所需的所有方法和属性的公共基类,并让这两个类派生出来。然后,您可以始终转换为基类。
事实上这似乎是理想的。特别是因为如果需要,您始终可以使用虚方法自定义基类中的行为。
如果这在您当前的任务中不起作用,也许您应该更多地讨论为什么需要这个。
答案 1 :(得分:0)
您要为D2
编写一个构造函数,该构造函数需要const D1&
,或者您在D1
中编写一个返回D2
的转换运算符。您必须决定执行此转换的含义并适当地实施转换。
答案 2 :(得分:0)
您可以在派生类中添加一个构造函数,该构造函数采用Base模板:
template <class U>
D2(const Base<U> &other)
{
i2 = other.getV();
}
但不确定它是否符合您的需求。
答案 3 :(得分:0)
在您的示例中,我没有看到使用CRTP的原因。
Base
的特化都具有不依赖于模板参数的虚拟成员函数。您的代码建议此虚拟成员函数可用于访问创建从Base
的特化派生的任何类的实例所需的所有数据。如果我们遵循这个假设,人们可能会想到:
class Base
{
public:
virtual double getV() const = 0;
};
class D1 : public Base
{
int i;
public:
D1(int);
virtual double getV() const { return i; }
};
class D2 : public Base
{
int i;
public:
D2(int);
virtual double getV() const { return i; }
};
这仍然不允许转换。但是,在这里添加它们非常简单:
class D1 : public Base
{
int i;
public:
D1(int);
D1(Base const& p) : D1(p.getV()) {}
virtual double getV() const { return i; }
};
D1
而不是Base
应该允许此转换,因为只有D1
知道构建它所需的数据。
如果此处未显示的内容需要CRTP,您仍然可以使用公共基类:
class Common_base
{
public:
virtual double getV() const = 0;
};
template<class T>
class Base : public Common_base
{
};
class D1 : public Base<D1>
{
int i;
public:
D1(int);
D1(Common_base const& p) : D1(p.getV()) {}
virtual double getV() const { return i; }
};
如果出于某种原因,转换需要CRTP,您仍然可以使用转换构造函数模板:
template<class T>
class Base
{
public:
virtual double getV() const = 0; // whyever
};
class D1 : public Base
{
int i;
public:
D1(int);
template<class U>
D1(Base<U> const& p) : D1(p.getV()) {}
virtual double getV() const { return i; }
};