Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在嵌套类中实现多态性?_C++_Inheritance_Polymorphism_Nested Class - Fatal编程技术网

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

C++ 如何在嵌套类中实现多态性?,c++,inheritance,polymorphism,nested-class,C++,Inheritance,Polymorphism,Nested Class,编辑:底部的具体示例 解释这个问题的最好方法是举例说明(请注意,这个具体例子的解决方案不是我想要的答案) 假设我有一个基类base,它基本上是一个容器: class Base { protected: class BaseNode { protected: BaseNode* next; int id; }; Node* head; public: // ... functionality }; 现在我想推导并改进它,添加一个额外

编辑:底部的具体示例

解释这个问题的最好方法是举例说明(请注意,这个具体例子的解决方案不是我想要的答案)

假设我有一个基类
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
};
我想要的是一个
派生的
类,它具有
基本
的所有功能,但每个节点也包括一个
名称
,而不仅仅是一个
id

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

DerivedNode = {
    DerivedNode* next;
    int id;
    char* name;
};
但我得到的是:

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

更不用说
Base
类只处理
BaseNode
s。。。对
new
delete
的所有调用都无法为
DerivedNode
中的
char*
分配足够的内存

这似乎是一个非常普遍的问题,有什么好办法解决这个问题吗?大多数
Base
s功能甚至对
DerivedNode
s都非常有用,所以我更愿意保持继承方案的原样

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

我真的不想放太多的代码,所以我会尝试解释。。。如果有人想看一个例子,我问了一个关于我具体需求的问题

我正在实现一个
列表
类。那是我的基础课。它是模板化的(每个节点中的数据都是模板化的,每个节点也有*next和*prev字段),有一个迭代器嵌套类、插入、按迭代器位置删除。。。作品

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

因此:我将
Forrest
List
继承,并派生
ForrestNode
以包含指向数据的
TreeNode
列表:

class DerivedNode: public List<T>::ListNode {
    List<Tree<T*>::TreeNode*> treeNodes;
};
类DerivedNode:公共列表::ListNode{
列出三萜类化合物;
};
基类
List
不需要知道新的
treeNodes
字段,因为它与列表功能无关-像
swap
get\u head
is\u empty
这样的方法应该工作相同,创建新节点的工作应该基本相同(需要分配更多内存,但新的
treeNodes
字段不应使用数据初始化)


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

如@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;
}
#包括
使用名称空间std;
阶级基础{
受保护的:
模板
类BaseNode{
受保护的:
Z*下一步;
int-id;
};
公众:
};
类派生节点;
派生类:公共基{
私人:
类DerivedNode:公共BaseNode{
公众:
常量字符*名称;
void setId(int val){id=val;}
void setNext(DerivedNode*nx){next=nx;}
DerivedNode*getNext(){return next;}
};
DerivedNode*derHead;
公众:
派生的()
{
DerivedNode*node1=新的DerivedNode();
node1->name=“Nik”;
node1->setId(1);
node1->setNext(空);
DerivedNode*node2=新的DerivedNode();
node2->name=“Aka”;
node2->setId(2);
node2->setNext(空);
node1->setNext(node2);
derHead=节点1;
}
DerivedNode*getHead(){return derHead;}
作废打印()
{
DerivedNode*tmp=derHead;
while(tmp!=NULL)
{

cout您只需将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
};
类基{
受保护的:
模板
类BaseNode{
受保护的:
导出*下一步;
int-id;
};
节点*头;
公众:
//…功能
};
派生类:公共基{
私人:
类DerivedNode:公共BaseNode{
字符*名称;
};
公众:
//…更多功能
};

如果您确实需要多态性,这将非常困难,但因为您似乎没有使用多态性(
DerivedNode()->next->name
),您可能想看看如何用模板解决这个问题。您能分享一些这样的设计会有帮助的特定场景吗?这将如何解决分配问题?假设我在
Base
中有一个
insert
方法。它应该调用
new BaseNode()
…我必须重写
Derived
中的
insert
方法来调用
new-DerivedNode()
你能举个例子说明这个insert方法实际会做什么吗?它会将什么数据插入到你的数据结构中?你如何在不覆盖派生的insert方法的情况下将名称输入到节点中?insert方法会创建一个新节点并将其插入基类的开头(如列表),而
name
的默认构造函数对我来说已经足够好了,我将在
Derived
中编写方法来设置/获取名称。如果不将Base转换为模板,我看不到一个很好的解决方案。如果你想让Base能够通用地处理节点,我认为没有办法解决这个问题。我问@Kristian dazze这个问题评论中的问题:这将如何
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
};