指向组合接口的指针 - 指向实现一个接口并从另一个接口的实现扩展的类

时间:2016-12-31 19:22:10

标签: c++ inheritance interface multiple-inheritance

我有两个界面:

class FirstInterface
{
    virtual int getId() const = 0;
};

class SecondInterface
{
    virtual void setId(int id) = 0;
};

这是一个组合界面:

class CombinedInterface : public FirstInterface, public SecondInterface
{

};

这是第一个接口的具体类:

class FirstConcrete : public FirstInterface
{
    virtual int getId() const
    {
        return 1;
    }
};

现在,此类 CompleteConcrete 应该具有 CombinedInterface ,但希望同时重复使用 FirstConcrete 的实现。

class CompleteConcrete : public FirstConcrete, public SecondInterface
{
    virtual void setId(int id) { }
};

// This is wrong C++
// Cannot convert from CompleteConcrete * to CombinedInterface *
// CombinedInterface * combinedInterface = new CompleteConcrete();

当然这不起作用。 有没有人知道在C ++中实现这一目标的方法?

2 个答案:

答案 0 :(得分:1)

这是我在评论中提到的基于虚拟继承的解决方案:

class FirstInterface
{
    virtual int getId() const = 0;
};

class SecondInterface
{
    virtual void setId(int id) = 0;
};


class CombinedInterface : virtual public FirstInterface,
              virtual public SecondInterface
{

};

class FirstConcrete : virtual public FirstInterface
{
    virtual int getId() const
    {
        return 1;
    }
};

class CompleteConcrete : virtual public FirstConcrete,
             virtual public CombinedInterface
{
    virtual void setId(int id) { }
};

void example()
{
    CombinedInterface * combinedInterface = new CompleteConcrete();
}

使用虚拟继承,唯一需要的变化(除了房间里的大象)是CompleteConcrete乘以CombinedInterface而不是SecondInterface。你可以这样想:在图片中使用CompleteConcreate,它现在支持CombinedInterface,而不只是添加SecondInterface

对虚拟继承有些不满。我不。它是C ++的独特功能之一,没有其他高级语言共享,TMK。它是一个非常强大的工具,可以解决某些难以在其他方面解决的问题。虚拟继承的两个主要缺点是:

  1. 因为它如此强大,很容易被滥用,并导致各种问题。

  2. 如果虚拟继承的类具有非默认构造函数,它很快就会变得很痛苦,因为每个实际上都继承了某些东西的类现在负责构造它。

  3. 但是只要正确使用虚拟继承,并且所涉及的类可以自己构建,虚拟继承就是一个有用的工具。

    P.S。我还会提到一个刚想到的另一种替代解决方案。如果您说CombinedInterface只是因为某些特定功能可能需要它,例如:

     void somefunction(CombinedInterface &object);
    

    您的功能需要一个组合界面。

    做一个小改动:

     void somefunction(FirstInterface &first, SecondInterface &second);
    

    并将两个参数传递给同一个对象。您可以传递实现两个接口的CompleteConcrete,而不会对类层次结构进行任何更改。您还可以使用模板外观,使其看起来像函数仍然需要一个参数:

    template<typename T> void somefunction(T &&t)
    {
        real_somefunction(std::forward<T>(t), std::forward<T>(t));
    }
    
    void real_somefunction(FirstInterface &first, SecondInterface &second);
    

    你几乎可以摆脱CombinedInterface,只需将实现两个接口的任何对象传递给somefunction(),你的real_somefunction()将使用一个或另一个参数来调用相应的接口

    假设您需要携带指向实现两个接口的对象的指针?

    class combined_pointer : public std::pair<FirstInterface *, SecondInterface *> {
    
    public:
        template<typename T> combined_pointer(T *t)
                : std::pair<FirstInterface *, SecondInterface *>(t, t)
        {}
    };
    

    只是一个起点。

答案 1 :(得分:0)

我使用了虚拟继承。

这已成功编译并发出警告,但我认为没问题。

class FirstInterface
{
    virtual int getId() const = 0;
};

class SecondInterface
{
    virtual void setId(int id) = 0;
};

class CombinedInterface : virtual public FirstInterface, public SecondInterface
{

};

class FirstConcrete : virtual public FirstInterface
{
    virtual int getId() const
    {
        return 1;
    }
};


class CompleteConcrete : public CombinedInterface, public FirstConcrete
{
    virtual void setId(int id) { }
};


// warning: C4250:  inherits via dominance
CombinedInterface * combinedInterface = new CompleteConcrete();