【问题标题】:diamond inheritance - Passing leaf class object as parameter in place of root class钻石继承 - 传递叶类对象作为参数代替根类
【发布时间】:2013-10-12 04:45:34
【问题描述】:

我有一个具有以下继承结构的程序

                       List
                   /         \
          DoublyLinkedList   CircularlyLinkedList
                   \          /
                CircularlyDoublyLinkedList


List 类(完全抽象)中,我有一个纯虚函数

     int virtual insert(List **head, int position) = 0;

我在 DoublyLinkedListCircularlyLinkedList 类中覆盖了它。
为了解决CircularlyDoublyLinkedList 类中的歧义,我使用范围解析运算符:: 明确指定要继承的insert() 函数的哪个版本,例如:DoublyLinkedList::insert(..)

我的问题是这个语句

    List *cdll_head = new CircularlyDoublyLinkedList();

抛出错误

    "cannot convert CircularlyDoublyLinkedList* to  List*"

当我将语句更改为

    CircularlyDoublyLinkedList *cdll_head = new CircularlyDoublyLinkedList();

我收到另一个错误,因为 insert(...) 接受了 List** 类型的参数

如何在没有演员表的情况下解决此问题?

【问题讨论】:

    标签: c++ inheritance diamond-problem


    【解决方案1】:

    当使用菱形结构的多重继承时,您应该使用虚拟继承。

    我假设你的代码看起来有点像这样:

    class List {
    ...
    };
    
    class DoublyLinkedList: public List {
    ...
    };
    
    class CircularlyLinkedList: public List {
    ...
    };
    
    class CircularlyDoublyLinkedList: public DoublyLinkedList, public CircularlyLinkedList {
    ...
    };
    
    void doStuff() {
        List* aList = new CircularlyDoublyLinkedList();
        ...
    }
    

    会产生以下错误:

    ambiguous conversion from derived class 'CircularlyDoublyLinkedList' to base class 'List':
        class CircularlyDoublyLinkedList -> class DoublyLinkedList -> class List
        class CircularlyDoublyLinkedList -> class CircularlyLinkedList -> class List
    

    如果您将 DoublyLinkedList 和 CircularlyLinkedList 的继承更改为 virtual public,如下所示:

    class DoublyLinkedList: virtual public List {
    ...
    };
    
    class CircularlyLinkedList: virtual public List {
    ...
    };
    
    class CircularlyDoublyLinkedList: public DoublyLinkedList, public CircularlyLinkedList {
    ...
    };
    

    一切都应该正确编译。但是,有一个additional performance cost。我建议使用一个完全抽象的列表接口,它可以被所有列表类继承,并使用组合来允许实现重用。

    【讨论】:

    • 非常感谢耐心的回复。我的列表基类是完全抽象的,所有函数都是纯虚拟的。我在 CircularlyDoubly 插入函数中做了类似 DoublyLinked::insert() 的操作,所以是虚拟的需要继承吗?
    猜你喜欢
    • 1970-01-01
    • 2020-10-03
    • 2020-01-01
    • 2011-12-28
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 2022-07-10
    • 2013-05-16
    相关资源
    最近更新 更多