【问题标题】:A pointer to a combined interface - point to a class implementing one and extending from an implementation of the other指向组合接口的指针 - 指向实现一个接口并从另一个实现扩展的类
【发布时间】:2017-05-15 15:12:30
【问题描述】:

我有两个接口:

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++ 实现这个目标的方法吗?

【问题讨论】:

  • 我可以使用虚拟继承来完成这项工作,并对层次结构进行一点小调整。如果您可以使其余的东西与虚拟继承一起使用,那将是一个答案。如果您不知道虚拟继承是什么意思,那么这可能不适合您。
  • 你真的需要CombinedInterface 吗?
  • 您可以使用组合来重用实现。
  • @SamVarshavchik 我知道什么是虚拟继承,我不喜欢必须使用该技术的想法,但如果它能够实现目标而没有严重的副作用,我会使用它。请发表您的答案。
  • @Jarod42 是的,我需要它。它就像数据库的 ReadInterface 和 WriteInterface。现在我需要提供一个指向数据库的 ReadWriteInterface 的指针。有些客户端只需要 ReadInterface .. 有些需要两者。

标签: c++ inheritance interface multiple-inheritance


【解决方案1】:

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

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();
}

使用虚拟继承,唯一需要的更改(除了房间里的大象)是从CombinedInterface 获得CompleteConcrete multiply-inherit,而不是SecondInterface。你可以这样想:图中有CompleteConcreate,现在支持CombinedInterface,而不仅仅是增加了SecondInterface

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

  1. 因为功能强大,很容易被误用,导致各种问题。

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

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

附:我还将提到刚刚想到的另一种替代解决方案。如果说你有你的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)
    {}
};

只是一个起点。

【讨论】:

  • 很好的解释和介绍其他解决方案。我需要告诉你为什么我真的需要CombinedInterface。我正在实现一个返回指向组合接口的指针的工厂。这就是为什么玩两个接口的技巧不起作用的原因。
【解决方案2】:

我使用过虚拟继承。

这个编译成功,但有警告,但我认为没问题。

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();

【讨论】:

  • 是的,没关系。您可以永久禁止警告 C4250。你想要通过支配来继承。我不知道为什么 MS 编译器开发人员认为这是一件坏事。
猜你喜欢
  • 1970-01-01
  • 2016-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
  • 1970-01-01
  • 2019-02-14
相关资源
最近更新 更多