如何在嵌套类中实现多态?

时间:2014-11-21 09:43:24

标签: c++ inheritance polymorphism nested-class

编辑:底部的具体示例

解释问题的最佳方法是通过示例(请注意,此特定示例的解决方案不是我正在寻找的答案)。

假设我有一个基类Base,它基本上是一个容器:

class Base {
protected:
    class BaseNode {
    protected:
        BaseNode* next;
        int id;
    };
    Node* head;
public:
// ... functionality
};

现在我想得到并改进它,添加一个额外的数据字段:

class Derived : public Base {
private:
    class DerivedNode: public BaseNode {
        char* name;
    };
public:
// .. some more functionality
};

我想要的是具有Derived所有功能的Base类,但每个节点还包含name,而不只是id

但如果我查看DerivedNode的实例,我想要的将是:

DerivedNode = {
    DerivedNode* next;
    int id;
    char* name;
};

但我拥有的是:

DerivedNode = {
    BaseNode* next;
    int id;
    char* name;
};

所以DerivedNode()->next->name将是未定义的!

更不用说Base类只处理BaseNode ...所有对newdelete的调用都不会为{{1}分配足够的内存在char*

这似乎是一个非常通用的问题,有一些巧妙的解决方法吗?大多数DerivedNode的功能对于Base来说都非常有用,所以我更愿意保留继承方案......

编辑:此时可能有用的具体示例

我真的不想放大量的代码,所以我会尝试解释......如果有人想看一个例子,我已经问了一个关于我的具体需求的问题here

我正在实施DerivedNode课程。那是我的基础。它是模板化的(每个节点中的数据都是模板化的,每个节点也有* next和* prev字段),有一个迭代器嵌套类,插入,通过迭代器位置移除......工作。

我想实现一个List类,它是一个数据节点列表(仍然是模板化的),但每个节点都包含一个指向该节点的Forrest列表。我想这样做是因为数据是可排序的,我希望能够在TreeNode时间内获取它(因此,树),但它可以通过两种不同的方式(例如,年龄和ID号)进行排序,所以我需要两棵树指向相同的数据。

所以:我使log(n)继承自Forrest,并派生List以包含指向数据的ForrestNode列表:

TreeNode

基类class DerivedNode: public List<T>::ListNode { List<Tree<T*>::TreeNode*> treeNodes; }; 无需了解新的List字段,因为它与列表功能无关 - treeNodesswap等方法, get_head应该工作相同,创建一个新节点应该工作几乎相同(需要分配更多内存,但新的is_empty字段永远不应该用数据初始化。)

然而,新的treeNodes类将覆盖基本Forrest方法,但仅限于添加功能 - 例如,在插入(常规列表插入)之后,指针将插入相关树中,然后新树节点的地址将添加到List列表中。

2 个答案:

答案 0 :(得分:0)

如@stefaanv所述,我们可以使用模板来实现您想要的效果。请验证以下程序:

#include <iostream>

using namespace std;


class Base {

protected:

    template<typename Z>
    class BaseNode{

    protected:

        Z* next;
        int id;
    };

public:

};


class DerivedNode;


class Derived : public Base{

private:

    class DerivedNode: public BaseNode<DerivedNode>{

        public:
        const char* name;

        void setId(int val){id = val;}
        void setNext(DerivedNode* nx){next = nx;}
        DerivedNode* getNext(){return next;}


    };

    DerivedNode* derHead;

public:


  Derived()
  {
      DerivedNode* node1 = new DerivedNode();

      node1->name = "Nik";
      node1->setId(1);
      node1->setNext(NULL);



      DerivedNode* node2 = new DerivedNode();

      node2->name = "Aka";
      node2->setId(2);
      node2->setNext(NULL);

      node1->setNext(node2);

      derHead = node1;
  }
  DerivedNode* getHead(){return derHead;}

  void print()
    {
       DerivedNode* tmp = derHead;
       while(tmp != NULL)
       {
           cout<<tmp->name<<endl;
           tmp = tmp->getNext();
       }

    }
};



int main()
{
   Derived obj;
   obj.print();

   return 0;
}

答案 1 :(得分:0)

您可以简单地将Base :: BaseNode转换为模板,并提供next成员变量的类型作为类型参数,如下所示:

class Base {
protected:
    template <class Derived>
    class BaseNode {
    protected:
        Derived* next;
        int id;
    };
    Node* head;
public:
// ... functionality
};

class Derived : public Base {
private:
    class DerivedNode: public BaseNode<DerivedNode> {
        char* name;
    };
public:
// .. some more functionality
};