我有一个模板Node,它返回T类型的数据。
template <class T> Node
{
public:
virtual const T& GetData() = 0;
};
我想要派生类RefNode,以及包含数据指针和实际数据的ValueNode。这样我就可以选择是使用数据副本还是处理节点中的实际数据。
template<class T> class RefNode : public Node<T>
{
public:
RefNode(T *_data) : data(_data) { }
const T& GetData() { return *data; }
protected:
DataType *data;
};
template<class T> class ValueNode : public Node<T>
{
public:
ValueNode(const T&_data) : data(_data) { }
const T& GetData() { return data; }
protected:
T data;
};
我知道模板不能有虚拟方法,但我只想说明我想要的效果。我想得到的效果是:
//用于类Vector
Vector v, *c;
c = new Vector();
Node<Vector>* node = new RefNode<Vector>(c);
Node<Vector>* node2 = new ValueNode<Vector>(a);
node2->GetData(); //calls ValueNode<Vector>'s GetData();
node->GetData(); //calls RefNode<Vector>'s GetData();
C ++中是否有任何方法可以实现这种行为?
修改
我会像这样使用GetData():
Vector *vecarr[9];
Node<Vector>* nodes[10];
nodes[0] = new RefNode<Vector>(vecarr[0]);
nodes[1] = new ValueNode<Vector>(Vector(2,3)); //non reference vector
nodes[2] = new RefNode<Vector>(vecarr[1]);
nodes[3] = new RefNode<Vector>(vecarr[2]);
.....
void processPositionNodes(Node<Vector> **nodes, int n)
{
for(int i=0; i< n; i++) //iterate over all nodes
{
Vector vec = nodes[i]->GetData();
//do something with vec
}
}
我希望能够更改Node包含的数据类型,因为我想实现几种处理不同类型数据的图算法(Vector,scalars ..)
答案 0 :(得分:0)
正如评论中指出的,模板确实可以具有虚拟功能。但是,这不会解决您的问题。实际上,您需要这些函数具有不同的返回类型。
这是一个可能的基于模板的解决方案,它可能不是最优雅的,但你(我们)可以在此基础上工作
#include <iostream>
using namespace std;
template <typename T, template<typename> class Accessor, template<typename> class Traits>
class Node{
public:
Node() : data(5.){}
typedef typename Traits<T>::type getType;
getType get(){
return static_cast<Accessor<T>*>(this)->implementation();
}
virtual ~Node(){}
protected:
T data;
};
template <typename T>
struct TraitsP{
typedef T* type;
};
template <typename T>
class PointerAccessor : public Node<T, PointerAccessor, TraitsP>{
public:
typename TraitsP<T>::type implementation(){
return &(Node<T, PointerAccessor, TraitsP>::data);
}
};
template <typename T>
struct TraitsD{
typedef T type;
};
template <typename T>
class DirectAccessor : public Node<T, DirectAccessor, TraitsD>{
public:
typename TraitsD<T>::type implementation(){
T ret = Node<T, DirectAccessor, TraitsD>::data;
return ret;
}
};
int main(){
auto np = new PointerAccessor<double>();
double* p = np->get();
cout << *p << endl;
auto np2 = new DirectAccessor<double>();
double d = np2->get();
cout << d << endl;
}
这个解决方案可能看起来很奇怪,PointerAccessor是由Node \&lt; ...,PointerAccessor,...&gt;派生的。这就是所谓的Curiously Recurring Template Pattern (CRTP)
答案 1 :(得分:0)
此代码工作正常(对您的版本进行了一些次要和不相关的更改):
#include <iostream>
using namespace std;
template <class T>
class Node
{
public:
virtual const T& GetData() = 0;
};
template<class T>
class RefNode : public Node<T>
{
public:
RefNode(T *_data) : data(_data) { *data = 5; }
const T& GetData() { return *data; }
protected:
T *data;
};
template<class T> class ValueNode : public Node<T>
{
public:
ValueNode(const T&_data) : data(_data) { data = 5; }
const T& GetData() { return data; }
protected:
T data;
};
int main(){
double data;
Node<double>* rn = new RefNode<double>(&data);
Node<double>* rv = new ValueNode<double>(data);
const double& a = rn->GetData();
const double& b = rv->GetData();
cout << a << '\t' << b << endl;
}
但是,此代码存在一些潜在问题:类Node中缺少虚拟析构函数,缺少copy ctor,dtor和operator =在类RefNode中