Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.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++_Multiple Inheritance - Fatal编程技术网

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

C++:处理这种多重继承的最佳方法是什么?,c++,multiple-inheritance,C++,Multiple Inheritance,页面基本上是一个固定大小的数组类型,但它提供了其他功能,这对于这个问题并不重要。具体来说,每个页面都有一个recordOffset,这意味着页面的记录ID是连续的,并且从该索引开始。页面可以被视为较大数组中的一个离散的任意段 class AbstractPage { protected: unsigned int recordOffset; public: AbstractPage(unsigned int recordOffset);

页面基本上是一个固定大小的数组类型,但它提供了其他功能,这对于这个问题并不重要。具体来说,每个页面都有一个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;
};
到目前为止还不错,但这是一个两难的问题;我需要扩展每个类型以创建页面的索引版本:

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

class IndexedIntegerPage : public AbstractIndexedPage, public IntegerPage
{
};
问题是返回的对象将不具有AbstractPage的接口:

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

我的选择是:

AbstractIndexedPage扩展了AbstractPage并使用虚拟继承,因为现在将有两个AbstractPage。但这将为我提供完整的界面。但这不是一个顽皮的黑客吗? 只需在IndexedIntegerPage和IntegerPage中复制数据或RecordId实例变量,即可提供相同的功能,而无需继承。 以不同的方式设计架构?
谢谢

我本来打算在评论中发表这篇文章的,但是代码看起来很糟糕。您可以考虑在较低级别上抽象:创建一个任意类型,并基于它创建一个页面类型:

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;
};
然后,对于索引品种,它不再是多重继承:

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

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

当然,要验证所有可能的错误或例外


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

你认为是授权吗?其中AbstractIndexedPage有一个AbstractPage类型的成员,而ConcreteIndexedPage的任何实例都被一个ConcretePage实例标记。您能进一步解释吗?如果AbstractInstancePage中有一个AbstractPage实例,那么AbstractInstancePage仍然需要在AbstractInstancePage之上公开AbstractPage中的所有方法?不,当您需要对AbstractClass执行某些操作时,你要求AbstractIndexedPage给你一个对AbstractClass对象的引用,并按计划完成工作,例如,获取计数。啊,我明白了。是的,这将是一个完全合法的解决方案。但是现在我更好奇的是,两个接口是否可以由一个实例安全地提供。我认为您使用了IndexedIntegerPage而不是AbstractIndexedPage,您可以毫无问题地调用sortedPage.getCount。问题是AbstractIndexedPage对AbstractPage一无所知。它最初是用C编写的,使用void*数据,到处使用switchtype。我不喜欢C++,因为我希望包含字符串或更复杂数据的特殊类型的页面在自已包含的类中有逻辑,而不会污染一个大类。哦,不,我想我的根正在显现。你说得很对,随着页面类型的增加,这个解决方案会变得更糟。@ElliotChance,现在我想起来了,需要切换的地方在哪里?可能是在处理数据时。在这种情况下,您可以创建一个AbstractData类,其中包含不同类型的具体实现。在AnyPage的构造函数中,您可以选择适当的具体数据类,例如,在接受vector的AnyPage构造函数中,您可以创建IntData——瞧,不需要切换。所以,我想这相当于增加了一层抽象。到目前为止,这是我最喜欢的解决方案。我还是想知道是否有办法把它们组合在一起。也许分离AbstractPage的纯接口并将其应用回AbstractPage和AbstractIndexedPage,然后创建从AbstractIndexedPage到包含实例变量的AbstractPage各自方法的转发器方法?可能有效,但也会产生更多需要的工作。。。
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
}
AbstractIndexedPage sortedPage = sort(originalPage);
sortedPage.getCount(); // can't do this!
dynamic_cast<AbstractPage>(sortedPage).getCount() // can do this, but pretty messy
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.data[0].f = 12.34;
class AnyIndexedPage : public AnyPage
{
public:
    // this is instead of the recordOffset of AnyPage
    vector<unsigned int> recordIds;
};
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!