如何使变量类型多态起作用?
Posted
技术标签:
【中文标题】如何使变量类型多态起作用?【英文标题】:How to make variable type polymorphism work? 【发布时间】:2013-07-09 14:03:02 【问题描述】:我有一个模板节点,它返回 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 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
我希望能够更改节点包含的数据类型,因为我想实现几种处理不同类型数据的图形算法,(向量、标量..)
【问题讨论】:
模板可以有虚函数。 “我知道模板不能有虚方法”——呃什么?您可能正在考虑 模板化 虚函数。 问题是:当你收到这种调用GetData()的结果时,你想如何使用它?我可能错了,但我不认为你真的想要一个基于多态的解决方案。您可能想要的是能够将策略“注入”到节点中,该策略应该能够更改与 GetData 成员的返回类型相关的行为。如果您确认这将是您的解决方案,我可以根据此得出答案。否则,请添加一个示例,说明您应该如何使用 GetData 的输出 顺便说一句,RefNode
既接受指针又存储指针有点用词不当。 C++ 既有引用又有指针。
我编辑了我的帖子,并举例说明了如何使用 GetData()。你说得对,我的意思是模板化的虚函数,它返回变量类型的参数。
【参考方案1】:
这段代码可以正常工作(您的版本有一些小的和不相关的更改):
#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 类中缺少虚拟析构函数,RefNode 类中缺少复制 ctor、dtor 和 operator=
【讨论】:
恐怕我之前的答案偏离了轨道,我把它留在那里。告诉我这是否能解决您的问题,如果前一个问题偏离轨道,我会立即删除它。 好的,谢谢!这解决了我的问题,CRTP 不适合我的目的,因为我需要能够从基类类型的指针调用派生类函数,即我需要动态绑定。【参考方案2】:正如 cmets 中所指出的,模板确实可以具有虚函数。但是,这并不能解决您的问题。事实上,您需要这些函数具有不同的返回类型。
这可能是针对您的问题的基于模板的解决方案,它可能不是最优雅的,但您(我们)可以在此基础上工作
#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\<... pointeraccessor ...> 派生的。这就是所谓的Curiously Recurring Template Pattern (CRTP)
【讨论】:
以上是关于如何使变量类型多态起作用?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用户定义的运行时属性在 xcode 10.2.1 和 ios 12.2 中起作用
为啥 == 在比较具有相同 int 值的两个对象类型变量时不起作用