编辑:底部的具体示例
解释问题的最佳方法是通过示例(请注意,此特定示例的解决方案不是我正在寻找的答案)。
假设我有一个基类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
...所有对new
和delete
的调用都不会为{{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
字段,因为它与列表功能无关 - treeNodes
,swap
等方法, get_head
应该工作相同,创建一个新节点应该工作几乎相同(需要分配更多内存,但新的is_empty
字段永远不应该用数据初始化。)
然而,新的treeNodes
类将覆盖基本Forrest
方法,但仅限于添加功能 - 例如,在插入(常规列表插入)之后,指针将插入相关树中,然后新树节点的地址将添加到List
列表中。
答案 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
};