C++:处理这种多重继承的最佳方法是什么

C++: what is the best way to handle this multi-inheritance?

本文关键字:最佳 方法 是什么 多重继承 处理 C++      更新时间:2023-10-16

页面基本上是一个固定大小的类型数组,但它提供了其他对这个问题不重要的功能。具体来说,每个页面都有一个recordOffset,这意味着该页面的记录ID是连续的,并从该索引开始(页面可以被视为较大阵列的离散任意段)

class AbstractPage
{
    protected:
        unsigned int recordOffset;
    public:
        AbstractPage(unsigned int recordOffset);
        virtual ~AbstractPage();
        // a mixture of pure and non-pure virtual functions
        virtual string toString() const;
        virtual unsigned int getCount() const = 0;
        virtual PageType pageType() const = 0;
};
class IntegerPage : public AbstractPage
{
    public:
        vector<int> data;
        IntegerPage(const vector<int>& data);
        virtual ~IntegerPage();
        // our concrete implementation
        virtual unsigned int getCount() const;
        virtual PageType pageType() const;
};
class FloatPage : public AbstractPage
{
    public:
        vector<float> data;
        FloatPage(const vector<float>& data);
        virtual ~FloatPage();
        // our concrete implementation
        virtual unsigned int getCount() const;
        virtual PageType pageType() const;
};

我不想为此使用模板,因为这些页面被这样使用;

LinkedList<AbstractPage> pages;

在大多数情况下,我将使用AbstractPage提供的接口方法与页面进行交互。当我需要直接读/写数据时,我会单独知道类型并使用:

dynamic_cast<FloatPage>(abstractPage).data[0] = 12.34;

到目前为止还不错,但这是一个进退两难的问题;我需要扩展每种类型来创建页面的索引版本:

class AbstractIndexedPage
{
    public:
        // this is instead of the recordOffset of AbstractPage
        vector<unsigned int> recordIds;
};
class IndexedIntegerPage : public AbstractIndexedPage, public IntegerPage
{
};

现在我想能够做到这一点:

AbstractIndexedPage sort(const AbstractPage& page)
{
    // Sorting will swap around the data and therefore we need to keep track of the
    // record IDs in an Indexed page.
    // If the incoming concrete type is IntegerPage, the output will be
    // IndexedIntegerPage
}

问题是返回的对象将没有到AbstractPage:的接口

AbstractIndexedPage sortedPage = sort(originalPage);
sortedPage.getCount(); // can't do this!
dynamic_cast<AbstractPage>(sortedPage).getCount() // can do this, but pretty messy

根据我所读到的,除了select之外,所有情况下的多重继承都意味着你的代码基本上设计得很糟糕。在这种情况下,有来自两个非接口的多重继承,这两个类都将有一个构造函数(和虚拟析构函数),但只能直接处理它们提供的实例变量。

我的选择是:

  1. AbstractIndexedPage扩展了AbstractPage并使用virtual继承,因为现在将有两个AbstractPage。但这将给我完整的界面。但这不是一个顽皮的黑客吗
  2. 只需在IndexedIntegerPageIntegerPage中复制datarecordIds实例变量,即可在不需要继承的情况下提供相同的功能
  3. 以不同的方式设计架构

感谢

您可以使用委派来完成这项工作。例如,在AbstractIndexedPage:

class AbstractIndexedPage
{
    public:
        // this is instead of the recordOffset of AbstractPage
        vector<unsigned int> recordIds;
        AbstractClass* getPage() { return page;};
    private:
        AbstractClass *page;
};

做一些类似的事情:

AbstractIndexedPage sortedPage = sort(originalPage);
sortedPage.getPage()->getCount(); // can't do this!

当然,要核实所有可能的错误或解释。

附言:有人会告诉你使用智能指针,我会同意他们的意见,但为了简单起见,我只使用普通指针

我本来打算在评论中发布这篇文章,但代码看起来很糟糕。您可以考虑在较低级别进行抽象:创建一个AnyType,并在此基础上创建一个页面类型:

union AnyType {
    float f;
    int i;
};
class AnyPage : public AbstractPage
{
public:
    enum PageDataType {FloatPage, IntPage};
    vector<AnyType> data;
    AnyPage(const vector<int>& data); //creates an 'IntPage'
    AnyPage(const vector<float>& data); //creates a 'FloatPage'
    virtual ~AnyPage();
    // our concrete implementation
    virtual unsigned int getCount() const;
    virtual PageType pageType() const;
private:
    PageDataType myType;
};

然后你可以创建AnyPage的链接列表,正如你所说,当你想访问数据时,你已经知道你要处理的是哪种页面:

anyPage.data[0].f = 12.34;

然后,对于索引品种,它不再是多重继承:

class AnyIndexedPage : public AnyPage
{
public:
    // this is instead of the recordOffset of AnyPage
    vector<unsigned int> recordIds;
};