Diamond inheritence - 继承自抽象类,也是一个具体的类,而不是实现基于共享的类

问题描述 投票:1回答:1

请考虑:

IReferenceCounting是一个纯抽象类,使用方法AddRef和RemoveRef

virtual void AddRef() noexcept = 0;
virtual void RemoveRef() noexcept = 0;

我没有建立这个类,也不能改变它。

现在我有另一个类,我构建了一个名为ISoundComponent的类,它继承自IReferenceCounting。类ISoundComponent也是抽象的(一开始它不包含AddRef或Release的定义)。

由于每个继承自IReferenceCounted的组件都需要实现AddRef和RemoveRef,因此存在ReferenceCountedImpl,它继承自IReferenceCounted。我没有建立这个类,我无法改变它。

最后,我有另一个我构建的类,比如SoundDiagnostics,它继承自ISoundComponent和ReferenceCountedImpl

很多人已经看过了 - 我有钻石继承问题。通过不提供我自己的AddRef和RemoveRef,而是使用ReferenceCountedImpl,意味着我需要ISoundComponent和ReferenceCountedImpl来虚拟地继承IReferenceCounted ...正确吗?

不幸的是我无法编辑只有ISoundComponent的ReferenceCountedImpl。这是因为IReferenceCounting和ISoundComponent存在于我们的代码库中的许多项目中,但是ReferenceCountedImpl只存在于一个项目中(SoundDiagnostics存在于同一个项目中)。这是有道理的,因为项目可以决定它如何实现IReferenceCounting,我们应该能够在该项目的不同类中重用它。

不幸的是,因为我不能去编辑ReferenceCountedImpl,所以我无法构建这个,因为钻石继承问题(SoundDiagnostics不知道是否要调用ReferenceCountedImpl :: AddRef或ISoundComponent :: AddRef)。

我觉得我正在咆哮错误的树,错过了一些明显的东西,陷入了虚拟继承的细节和/或我的设计搞砸了。代码库组织应该对此问题不可知。谁能给我一些关于如何构建它的指导?我认为没有从IReferenceCounted虚拟继承的ReferenceCountedImpl是解决方案 - 例如执行此操作时需要考虑性能原因。

有兴趣学习如何解决这个问题。

编辑:

// available across all projects in code base
class IReferenceCounted
{
    virtual void AddRef() = 0;
    virtual void RemoveRef() = 0;
};

// available across a few select projects in the codebase (ones that wish to use some kind of sound component)
class ISoundComponent : public virtual IReferenceCounted
{
    virtual void Play() const = 0;
};

// available within one specific project, SoundDiagnostics. I cannot modify this
class ReferenceCountedImpl : public IReferenceCounted
{
    void AddRef() override
    {
        m_refcount++;
    }

    void RemoveRef() override
    {
        if (--m_refcount == 0)
        {
            delete this;
        }

    }

    int m_refcount = 0;
};

// available within one specific project, SoundDiagnostics.
class SoundDiagnostics : public ISoundComponent, public ReferenceCountedImpl
{
    void Play() const override
    {
        return;
    }

    void RunDiagnostics()
    {

    }
};

// function within my SoundDiagnostics project
int main()
{
    SoundDiagnostics soundDiagnostics;
    return 0;
}

试图编译这将产生

不允许使用抽象类类型“SoundDiagnostics”的对象: 纯虚函数“IReferenceCounted :: AddRef”没有覆盖纯虚函数“IReferenceCounted :: RemoveRef”没有覆盖

如果ReferenceCountedImpl虚拟地从IReferenceCounted继承,那么此代码将成功编译。

c++ inheritance multiple-inheritance diamond-problem
1个回答
0
投票

我试图将你的描述变成代码。有用。

class IReferenceCounting {
public:
    virtual void AddRef() const noexcept = 0;
    virtual void RemoveRef() const noexcept = 0;
};
class IComponentPublicHeader :public virtual IReferenceCounting {};
class ReferenceCountedImpl :public virtual IReferenceCounting {
public:
    void AddRef() const noexcept override {};
    void RemoveRef() const noexcept override {};
};
class MyAmazingClass : IComponentPublicHeader, ReferenceCountedImpl {
    MyAmazingClass() {
        AddRef();// ReferenceCountedImpl::AddRef
    }
};

更新:我读了你的代码片段。如果AddRef和RemoveRef是公共的,你可以尝试像这样实现你的类。

class SoundDiagnostics : public ISoundComponent, public ReferenceCountedImpl
{
    void Play() const override
    {
        return;
    }
    void AddRef() override
    {
        ReferenceCountedImpl::AddRef();
    }

    void RemoveRef() override
    {
        ReferenceCountedImpl::RemoveRef();
    }
    void RunDiagnostics()
    {

    }
};

如果AddRef和RemoveRef是私有的,那么让ISoundComponent不继承IReferenceCounted。

class ISoundComponent
{
    virtual void Play() const = 0;
};
© www.soinside.com 2019 - 2024. All rights reserved.