我想我已经接近解决方案,但我错过了最后一步。 我想调用一个模板化的成员函数,我只有一个指针 到基类,类型已经预定义,所以不应该 取决于实际的参数类型。
这就是我所拥有的:
template <typename T> class TTemplateTest;
class CTemplateTest
{
public :
CTemplateTest(){};
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process(atValue);
}
};
//------------------------------
template <class T>
class TTemplateTest:public CTemplateTest
{
public :
TTemplateTest() : CTemplateTest(){};
virtual double Process(T atNewValue) {return atNewValue;};
};
//------------------------------
template <class T>
class TTemplateTestInt:public TTemplateTest<T>
{
public :
TTemplateTestInt(){};
virtual double Process(T atNewValue);
};
//------------------------------
template <class T> double TTemplateTestInt<T>::Process(T atNewValue)
{
return atNewValue;
}
CTemplateTest* pTTest = new TTemplateTestInt<int>();
// application code
double d = 5.5;
double r;
r = pTTest->Process(d);
我想在这个例子中将参数处理为整数, 无论论证是什么类型。它称之为正确的功能 但是值是垃圾,因为double被解释为整数 而不是转换。
我已经查看了其他问题(以及其他网站),但却没有 找到匹配或解决方案,例如 calling a template function of a derived class
解决方案可能是CRTP,但我无法弄清楚如何 使用它。应用程序代码应保持这样, 类定义可以改变。这段代码的原因是 它是从某些xml在运行时生成和使用的 配置文件。所以这种类型并不是真正知道的 功能调用。
如果我可以使用定义的类型,那可能会有所帮助,例如:
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process((this::type)atValue);
}
或者阻止使用double自动创建函数 所以参数会转换为整数 一个非模板化的函数。
感谢您的帮助。
编辑:下一个解决方案
这看起来有效吗?它不需要转换,我们只需要一些不同的基本类型的模板,因此不会有很多重定向器功能。它应该仍然有效(没有typeinfo等)。 我也发布它以防其他人有类似的问题。
class CTemplateTest
{
public :
CTemplateTest(){};
virtual inline double Process(double adValue)=0;
virtual inline double Process(int aiValue)=0;
};
//------------------------------
template <class T>
class TTemplateTest:public CTemplateTest
{
public :
TTemplateTest() : CTemplateTest(){};
virtual inline double Process(double adValue) {
return ProcessImp((T)adValue);
}
virtual inline double Process(int aiValue) {
return ProcessImpl((T)aiValue);
}
virtual double ProcessImpl(T atNewValue)=0;
};
//------------------------------
template <class T>
class CTemplateTestInt:public TTemplateTest<T>
{
public :
CTemplateTestInt(){};
virtual double ProcessImpl(T atNewValue) {return atNewValue;};
};
然后用
给出所需的结果CTemplateTest* pTTest = new TTemplateTestInt<int>();
// application code
double d = 5.5;
double r;
r = pTTest->Process(d);
// -> r = 5
由于
答案 0 :(得分:3)
您的代码在命名和逻辑方面看起来相当混乱。我不知道你想做什么,但我可以解释为什么你的代码会导致奇怪的行为,这也表明你的代码中存在一些基本的设计缺陷。
为简化起见,您的代码与此类似:
class A {};
class B : public A {};
class C : public A {};
int main () {
A *a_ptr = new B {};
C *c_ptr = static_cast<C*>(a_ptr);
}
没有reinterpret_cast
,但此代码仍会破坏类型系统,并会导致未定义的行为。因为B
与C
无关,即使它们都来自A
。
返回您的代码,class CTemplateTest
,功能
template <typename T> double Process(T atValue)
{
return static_cast<TTemplateTest<T>* >(this)->Process(atValue);
}
将通过模板参数推导获得类型T
,不从任何预定义类型获取。因此,pTTest->Process(d)
会将类型T
推断为双精度,并且在该函数中,static_cast
指向不相关指针this
的{{1}}指针。但是TTemplateTest<double>*
指针确实是this
,这两个类没有任何关系,除了两个类都来自TTemplateTest<int>*
。所以它只是简化的案例。
我不知道如何修复此代码......
答案 1 :(得分:1)
一些观察结果:
1)您的基类没有虚函数,但您的派生类每个都有唯一的,不相关的虚函数。它们不会覆盖任何东西,所以有点无意义是虚拟的。
2)基类不知道实例化派生类型的类型。当调用CTemplateTest :: Process时,该T是为函数调用推导出的参数,并且与用于派生类型的T无关。您只是将对象强制转换为使用您提供的类型实例化的模板,而忽略对象实际所在的类型。这说明了垃圾;这是未定义的行为。
3)没有模板虚拟功能这样的东西。非此即彼;接受你的选择。这基本上就是我认为你试图模拟的东西。您希望相同的函数采用任何类型的参数,并将其作为该类型传递给派生类型,派生类型知道如何以自己的模板方式处理它。我不确定一种令人满意的方法来实现这一目标。
一种想法是预先确定一组固定的类型,您将接受并单独处理它们,每个支持类型一个虚函数。您可以使用模板参数列表使其更加灵活,并使用编译器生成函数,但我完全没有想到这种方法。 :)