2010-03-25 71 views
1

我知道你不能虚拟一个虚拟功能,而且我理解它背后的概念。但我仍然需要一种方法来克服一些我得到的错误。我能够使我的东西工作,但它看起来不正确。有关虚拟功能模板化的问题

我有课称为System

#include "Vector.h" 
class System 
{ 
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0)  const = 0; 
}; 

class UnresolvedSystem : public System 
{ 
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0) const 
    { 
     //do something 
    } 
}; 

Vector.h

tenplate<typename T> 
class Vector 
{ 
    //some functions 
}; 

现在我想模板化的system.hVectorToLocal仅举Vector<T>,但我不能这样做,因为它是一个虚拟功能。我想要一个解决方法。我知道我可以有VectorToLocal作为参数,但我不想这样做,我需要Vector<float>Vector<double>等。

+0

'T'型是否有限制? – 2010-03-25 20:30:53

+0

T可以浮动,双重,复杂或复杂 jan 2010-03-25 21:01:41

回答

2

成员函数模板不能是虚拟的。没有两种方式。

但虚成员函数可以完全自定义的类型,只是碰巧使用模板:

class System 
{ 
public: 
    virtual void DoIt(vector<int>* v); 
}; 


int main() 
{ 
    vector<int> v; 
    System s; 
    s.DoIt(&v); 
    return 0; 
} 

顺便说一句,你为什么要实现自己的Vector类?

+0

我知道这就是我现在正在做的,我明确呼吁指定为载体,载体等我想知道是否有工作。 我正在使用我自己的Vector类,因为这与std :: vector完全不同,这是一个计算Dot产品,跨产品,幅度等的特殊类。 感谢您的即时回复。 – jan 2010-03-25 20:39:24

0

我不知道你想用你的矢量做什么,但有时可以使模板函数调用一个虚拟函数来实现实际行为。在这种情况下,你可以在你的超类中实现模板版本,并让它调用一个非模板的纯虚拟,它可以做任何你想做的事情。这通常只适用,如果你把类型参数的限制:

#include "Vector.h" 
class System 
{ 
    virtual void print(const std::string &) const = 0; 
    template<class T> 
    void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0) const { 
     print(T.GetName()); 
    } 
}; 

class UnresolvedSystem : public System 
{ 
    virtual void print(const std::string & Name) const { 
     std::cout << name << std::endl; 
    } 
}; 

在这种情况下,我认为T有一个成员函数GetName

+0

如果我想调用具有模板化参数的虚拟函数,怎么办?这个问题有可能吗? – jan 2010-03-25 20:49:58

+0

对不起,正如一些人已经指出的那样,没有办法使模板功能变为虚拟。但是,如果你更好地解释你试图达到的目标,我们可能会向你展示一个替代解决方案。 – 2010-03-25 22:02:51

0

如果您定义了C++模板函数,则会为每个模板参数类型组合创建一个新的函数实现。因此,源代码中的单个函数可以是机器代码中的一个函数或hunderds函数。这有助于使他们变得更快。

现在,编译器根据它的调用方式来确定函数的哪些版本。如果int永远不是类型参数,则编译器不会生成实现。现在,如果你打电话是虚拟的,很难发现它是如何使用的,当编译一个使用模板函数的函数时,函数的定义可能不在头文件中。没有函数的源代码,编译器不能创建编译函数。

当C++允许虚拟模板功能时,您还会遇到其他一些不切实际的情况。就像通常如何实现虚拟功能一样。

而这可能是C++不允许它的原因。你可能认为你需要它,但可能有另一种方法,我相信如果你给我们更多关于这段代码片段背后需求的细节,人们会帮助你找到答案。

0

你有几个选择,全部取决于你想要做什么。

如果T在某种程度上与System(例如,如果SystemT型)的成员变量,可以使模板就可以了整个班级:

template< typename T > 
class System 
{ 
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0)  const = 0; 
}; 

template< typename T > 
class UnresolvedSystem : public System<T> 
{ 
    virtual void VectorToLocal(Vector<T>& global_dir,const Vector<T>* global_pos = 0) const 
    { 
     //do something 
    } 
}; 

如果T的背景是本地VectorToLocal只,然后更好的设计决策。将因子的功能课外:

template< typename T > 
void VectorToLocal(System& s, Vector<T>& global_dir, ...) 
{ 
    // use s's public interface to make changes to the object 
} 

您能否提供更多关于VectorToLocal的用途的详细信息?

+0

我不能模仿系统类,因为它从称为实体类的实体和实体继承而来。对不起忘了提到我的问题。所以VectorToLocal有一些使用Vector做了一些数学运算,最后在类System中设置了一个成员变量。示例系统类包含名为RMat4的成员变量_mat,它实际上是一个4x4矩阵。 – jan 2010-03-26 14:16:48

+0

那么我会推荐第二种方法。使VectorToLocal()成为非成员模板函数,向System添加setMat(const RMat4 &newMat)函数,并使VectorToLocal()调用它。 – 2010-03-26 16:33:13

0

如果你想要的是提供一个单一的执行点,则可以将呼叫转移到一个模板

struct base { 
    virtual void f(int); 
    virtual void f(double); 
}; 

struct derived : base { 
    virtual void f(int x) { f_tmpl(x); } 
    virtual void f(double x) { f_tmpl(x); } 

    template <typename T> 
    void f_tmpl(T x) { // ... } 
}; 

我敢打赌,用类型串你实际上可以产生虚拟的功能,但是这可能只是复杂代码。

+0

其实这就是我现在实施的。它并不复杂,但它看起来像一个。 – jan 2010-03-26 13:20:38

1

任何消除虚拟功能的常见方法,如CRTP,也将有所帮助。

+0

CRTP代表奇怪的循环模板模式:http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern – 2010-03-26 16:34:58