用于表示单一继承的C ++数据结构

时间:2015-05-10 16:43:30

标签: c++ inheritance data-structures

我需要构建一个表示文件中存在的类的继承图的数据结构。这是为仅支持单继承的语言编写编译器的一部分。

存在的所有类的名称存储在链表中。我需要遍历该列表并从中构建一个继承图。 然后我需要检查继承中是否存在循环,例如 如果

    B inherits A
    C inherits B

然后

    A cannot inherit C. 

语言中不允许这样的循环。

哪种数据结构最适合这种情况?

3 个答案:

答案 0 :(得分:1)

鉴于继承通常不经常进行,并且因为层次结构通常不会变得非常深(例如,你通常不会在继承层次结构中拥有10,000多个类,更不用说1,000个),I认为只要您直接的链接结构就可以了。

A<->B<->C<---->A<->B<->C

当尝试将C链接到A时,首先在建立链接之前从A遍历图(树)(递归树搜索应该没问题)。如果您发现A已存在于A图表中,那么您需要建立一个周期并想要拒绝连接(生成编译器错误或其他内容)。

如果您发现这成为一个热点,并且您的特定编程语言实际上鼓励了一种编程方式,其中继承层次结构通常可以在其中包含大量类,那么这是一种简单的方法来优化从线性时间到logarithmic是存储std::shared_ptr<std::set<Node*>>

从A链接到B时,首先在A中搜索A中的共享std::set。如果B在该集合中不存在,那么我们可以自由建立连接( B继承自A)。然后将A中的shared_ptr复制到B。

在取消B与A的关联时(虽然我认为你不需要处理这个案例,因为有一种语言可以让事情变成“未被发现”),删除B从共享集中设置并将B的shared_ptr设置为null(释放引用)。

那就是说,你的语言真的允许在类定义之外进行这种动态继承吗?通常,大多数编程语言都会在定义类时指定继承。因此,除非你有这种&#34;动态继承&#34;,否则A通常不可能尝试从已经从B继承的B继承的C继承。这将试图使A继承在定义之后的很长一段时间内。

答案 1 :(得分:1)

游戏编程宝石8有一个伟大的“快速是一个”实现由我的老老板写,这将很好地适应这一点。我不记得所有的细节,所以你必须检查它,但它使用一些聪明的位模式技巧来快速做事(除了点打包)。 http://www.gameenginegems.net/gemsdb/article.php?id=516

答案 2 :(得分:1)

一个简单的树结构就足够了(在你的单一继承假设下)。

#include <iostream>
#include <cassert>
using namespace std;

class Class {
private:
    const string name;
    const Class *parent;
public:
    Class(const string aName) :
       name{aName},
       parent(nullptr)
    {}
    bool setParent(const Class &otherClass) {
        // I dont already have a parent class
        if (parent)
            return false;  // no multiple inheritance 
        // so I am the root of some inheritance tree.
        // Now searching for the root ot the otherClass tree
        auto root = &otherClass;
        while (root->parent != nullptr) {
           root = root->parent;
        };
        // it shouldn't be me !
        if (root == this)
            return false;
        // let's remember the inheritance
        parent = &otherClass;
        return true;
   }
};

// some tests
int main(int argc, char **argv)
{
     cout << "Tests :" << endl;
     Class a("A");
     assert(! a.setParent(a));
     Class b("B");
     assert(b.setParent(a));
     Class c("C");
     assert(c.setParent(b));
     assert( ! a.setParent(c));
     cout << "Success !" << endl;
     return 0;
 }

使用路径压缩技巧可以加快速度,请参阅http://en.wikipedia.org/wiki/Disjoint-set_data_structure#Disjoint-set_forests