C++ C++;类型多态性

C++ C++;类型多态性,c++,templates,inheritance,polymorphism,virtual,C++,Templates,Inheritance,Polymorphism,Virtual,我试图创建一个节点,该节点有一个类型为T的变量,T data以及存储指向其父节点的指针节点基*父节点 这些类看起来是这样的: class Node: public NodeBase { T data; NodeBase *parent; public: Node(T); void setData(T); T * getData(void); void setParent(NodeBase * const); NodeBase * getPa

我试图创建一个节点,该节点有一个类型为T的变量,
T data以及存储指向其父节点的指针
节点基*父节点

这些类看起来是这样的:

class Node: public NodeBase {
    T data;
    NodeBase *parent;
public:
    Node(T);
    void setData(T);
    T * getData(void);
    void setParent(NodeBase * const);
    NodeBase * getParent(void);
};

class NodeBase {
};
我原以为我可以在
节点库
中放置一个纯虚函数,但您必须指定返回类型,而且由于
节点库
没有类型,我无法指定
虚T*getData(void)=0

我遇到问题的具体案例:

Node<char> n1 = Node('A');
Node<int>  n2 = Node(63);
n1.setParent(&n2);

NodeBase *pNode = n1.getParent();
pNode->getData(); // Error: BaseNode has no member 'getData()'
Node n1=节点('A');
节点n2=节点(63);
n1.setParent(&n2);
NodeBase*pNode=n1.getParent();
pNode->getData();//错误:BaseNode没有成员“getData()”
您有pNode(child),因此您可以直接使用它来
getData()
,其次,您的基类对
getData()
一无所知,因此使用上置指针无法调用它


您有pNode(child),因此您可以直接使用它来
getData()
,其次,您的基类对
getData()
一无所知,因此使用上置指针您无法调用它。

我相信您混淆了运行时多态性和编译时多态性。模板提供了更晚的版本。解决此问题的一个可能方法是将
NodeBase
设置为模板类:

template <class T>
class NodeBase {
    public:
        virtual T getData() = 0;
};

template <class T>
class Node : NodeBase<T> {
    T data;
    NodeBase *parent;

public:
    Node(T);
    void setData(T);
    T getData(void);
    void setParent(NodeBase<T> * const);
    NodeBase<T> * getParent(void);
};
模板
类节点基{
公众:
虚拟T getData()=0;
};
样板
类节点:NodeBase{
T数据;
节点基*父节点;
公众:
节点(T);
无效设置数据(T);
T获取数据(无效);
void setParent(NodeBase*const);
NodeBase*getParent(无效);
};

注意,我让
getData
返回
T
,而不是
T*
。(是否有理由返回指针?

我认为您混淆了运行时多态性和编译时多态性。模板提供了更晚的版本。解决此问题的一个可能方法是将
NodeBase
设置为模板类:

template <class T>
class NodeBase {
    public:
        virtual T getData() = 0;
};

template <class T>
class Node : NodeBase<T> {
    T data;
    NodeBase *parent;

public:
    Node(T);
    void setData(T);
    T getData(void);
    void setParent(NodeBase<T> * const);
    NodeBase<T> * getParent(void);
};
模板
类节点基{
公众:
虚拟T getData()=0;
};
样板
类节点:NodeBase{
T数据;
节点基*父节点;
公众:
节点(T);
无效设置数据(T);
T获取数据(无效);
void setParent(NodeBase*const);
NodeBase*getParent(无效);
};

注意,我让
getData
返回
T
,而不是
T*
。(有返回指针的理由吗?

C++是静态类型的,所以每次编写这样的代码时:

NodeBase *pNode = n1.getParent();
pNode->getData(); // Error: BaseNode has no member 'getData()'
编译器需要知道
getData()
的类型。在您的例子中,您希望它是
int(void)
char(void)
-不返回参数的函数
char
int

这是有办法的。策略将取决于您的情况。返回类型有几种情况:

  • 一组固定的球头-使用一个接头
  • 一组固定的内置项或类,但类型永远不会更改-使用联合
  • 内置或类的修复集,但类型可能会更改-使用boost变体
  • 任何其他情况-使用boost Any
总之,向返回上述数据结构之一的基类(非模板化)添加一个虚拟函数。boost的文档很容易在网上找到

这是C++之所以困难的原因,是因为其他语言(尤其是动态语言)隐藏了困难。进行函数调用时,会分配空间(通常在堆栈上以获得最佳速度),并将返回值复制到该空间中。如果要返回未知类型,则需要在所有可能的返回类型(联合,可能是boost变量?)中提供最大可用空间,或者从堆中分配该空间(boost any)。许多静态类型语言仅为前者提供良好的支持

如果你想自己做的话,C++确实有一些有用的特性

#include <iostream>
#include <typeinfo>

using namespace std;

struct NodeBase {
    virtual ~NodeBase(){}
};

template<typename T>
struct Node: public NodeBase {
    T data;
    NodeBase *parent;

    Node(T data, NodeBase* parent = nullptr)
        : data(data), parent(parent)
    {}

    ~Node(){}
};

int main()
{
    Node<int>  n2(63);
    Node<char> n1('A', &n2);

    NodeBase* b = n1.parent; //pointer to n2

    if(typeid(*b) == typeid(Node<int>))
        cout << ((Node<int>*) b)->data << endl;

    return 0;
}
#包括
#包括
使用名称空间std;
结构节点基{
虚拟~NodeBase(){}
};
样板
结构节点:公共节点库{
T数据;
节点基*父节点;
节点(T数据,节点基*父节点=nullptr)
:数据(数据),父(父)
{}
~Node(){}
};
int main()
{
节点n2(63);
节点n1('A',和n2);
NodeBase*b=n1.parent;//指向n2的指针
if(typeid(*b)=typeid(节点))

cout dataC++是静态类型的,所以每次编写这样的代码时:

NodeBase *pNode = n1.getParent();
pNode->getData(); // Error: BaseNode has no member 'getData()'
编译器需要知道
getData()
的类型。在您的例子中,您希望它是
int(void)
char(void)
-不返回参数的函数
char
int

有很多解决方法。策略将取决于您的情况。退货类型有几种情况:

  • 一组固定的球头-使用一个接头
  • 一组固定的内置项或类,但类型永远不会更改-使用联合
  • 内置或类的修复集,但类型可能会更改-使用boost变体
  • 任何其他情况-使用boost Any
总之,向返回上述数据结构之一的基类(非模板)添加一个虚拟函数

这是C++中更困难的原因,因为其他语言(尤其是动态语言)隐藏困难。当进行函数调用时,会分配空间(通常在堆栈上以最佳速度分配),并将返回值复制到该空间中。如果要返回未知类型,则需要在所有可能的返回类型(union,可能是boost变量)中提供最大可用空间或者从堆中分配空间(boostany)。许多静态类型语言仅为前者提供良好的支持

如果你想自己做的话,C++确实有一些有用的特性

#include <iostream>
#include <typeinfo>

using namespace std;

struct NodeBase {
    virtual ~NodeBase(){}
};

template<typename T>
struct Node: public NodeBase {
    T data;
    NodeBase *parent;

    Node(T data, NodeBase* parent = nullptr)
        : data(data), parent(parent)
    {}

    ~Node(){}
};

int main()
{
    Node<int>  n2(63);
    Node<char> n1('A', &n2);

    NodeBase* b = n1.parent; //pointer to n2

    if(typeid(*b) == typeid(Node<int>))
        cout << ((Node<int>*) b)->data << endl;

    return 0;
}
#包括
#包括
使用名称空间std;
结构节点基{
虚拟~NodeBase(){}
};
样板
结构节点:公共节点库{
T数据;
节点基*父节点;