C++ C++;接口ptr的返回向量

C++ C++;接口ptr的返回向量,c++,templates,interface,polymorphism,c++14,C++,Templates,Interface,Polymorphism,C++14,我正在尝试创建一个接口,该接口返回一个接口向量,同时使用在另一端实现的接口 我知道这不清楚,所以这里有一些例子: class IComponent { public: virtual ~IComponent() {} virtual int getValue() const = 0; }; class ICollection { public: virtual ~ICollection() {} virtual IComponent* getComp

我正在尝试创建一个接口,该接口返回一个接口向量,同时使用在另一端实现的接口

我知道这不清楚,所以这里有一些例子:

class IComponent
{
  public:
    virtual ~IComponent() {}

    virtual int getValue() const = 0;
};

class ICollection
{
  public:
    virtual ~ICollection() {}

    virtual IComponent* getComp() = 0;
};

class Component : public IComponent
{
  public:
    virtual int getValue() const { return 42; }
};

class Collection : public ICollection
{
  public:
    Collection()
    {
      m_comp = new Component();
    }
    virtual Component* getComp()
    {
      return m_comp;
    }

  private:
    Component* m_comp;
};
这将编译并运行,因为
Component*
被隐式转换为
IComponent*
。这允许我使用完全实现的
集合
组件

#include <vector>

class IComponent
{
  public:
    virtual ~IComponent() {}

    virtual int getValue() const = 0;
};

class ICollection
{
  public:
    virtual ~ICollection() {}

    virtual std::vector<IComponent*> &getComp() = 0;
};

class Component : public IComponent
{
  public:
    virtual int getValue() const { return 42; }
};

class Collection : public ICollection
{
  public:
    Collection()
    {
      m_comp.push_back(new Component());
      m_comp.push_back(new Component());
    }
    virtual std::vector<Component*> &getComp()
    {
      return m_comp;
    }

  private:
    std::vector<Component*> m_comp;
};
如果更改返回类型,则集合将变为:

class Collection : public ICollection
{
  public:
    Collection()
    {
      m_comp.push_back(new Component());
      m_comp.push_back(new Component());
    }
    virtual std::vector<IComponent*> &getComp()
    {
      // This time this line is impossible without cast
      // because m_comp[0] is IComponent*
      std::cout << m_comp[0]->getDouble() << std::endl;
      return m_comp;
    }

  private:
    std::vector<IComponent*> m_comp;
};
类集合:公共ICollection
{
公众:
收藏()
{
m_组件推回(新组件());
m_组件推回(新组件());
}
虚拟std::vector和getComp()
{
//这一次,如果没有演员,这一行是不可能的
//因为m_comp[0]是IComponent*

std::cout getDouble()您需要将
Collection::getComp
的返回类型更改为
std::vector&
,因为否则它无法覆盖
ICollection::getComp
。因为
std::vector
也可以包含指向
组件的指针,所以只需将您的成员更改为该类型,您就可以了


如果某个地方需要指向
组件
而不是其接口的指针,则可以使用向下转换。

不确定此解决方案是否适用于您的情况,但是…如何在
ICollection
中将
组件
派生类作为模板参数传递

不完全是奇怪的重复模板模式,而是类似的模式

我是说,大概

template <typename CompT>
class ICollection
{
  public:
    virtual ~ICollection() {}

    virtual std::vector<CompT*> &getComp() = 0;
};
甚至,如果在模板类中转换
集合

template <typename CompT>
class Collection : public ICollection<CompT>
{
  public:
    Collection()
    {
      m_comp.push_back(new CompT());
      m_comp.push_back(new CompT());
    }
    virtual std::vector<CompT*> &getComp()
    {
      return m_comp;
    }

  private:
    std::vector<CompT*> m_comp;
};
模板
类集合:公共ICollection
{
公众:
收藏()
{
m_comp.推回(新CompT());
m_comp.推回(新CompT());
}
虚拟std::vector和getComp()
{
返回m_comp;
}
私人:
std::向量m_comp;
};

如果您知道返回的
向量的元素指向
组件
对象,您可以:

Collection coll;
std::vector<IComponent*>& v = coll.getComp();
Component& comp = *dynamic_cast<Component*>(v[0]);
coll;
std::vector&v=coll.getComp();
组件和组件=*动态_cast(v[0]);
如果您只需要
IComponent
接口中的虚拟方法,您甚至不需要强制转换;您可以使用动态分派来调用它们。但是强制转换到子类型的引用将获得它添加的任何方法

我还建议您减少抽象的泄漏。您可以通过
操作符[]
推送()/pop()
,或任何有意义的方式访问元素。这样,内部存储可以是任何类型指针的任何类型的容器,公共接口就不必更改


一个不太安全的选择是回到C方式
作为
IComponent**
,将其强制转换为
组件**
,然后返回该组件。

强制转换当然不是一个伟大的路线。请原谅显而易见的问题,但为什么不使用
std::vector
作为您的成员并返回引用类型。正如我刚刚在编辑中添加的,我希望能够在
Collec>中使用指向
组件
的指针tion
。如果我按照你说的做,我就做不到,或者至少我需要做一些其他“无用的”事情让它工作的东西。为什么使用指向
IComponent
的指针会在内部引起问题?这里没有,但如果我在
Component
中有更多的方法,我将无法使用这些方法。为了简单起见,这可能是您遗漏的内容,但我顺便指出,您的构造函数分配了两个
组件
堆中永远不会释放的对象,导致内存泄漏。您可以存储智能指针,也可以添加析构函数删除向量中的每个指针,所有这些都必须确保包含new分配的唯一指针。除非OP需要通过
ICollection
访问集合,否则效果很好。他或她是谁?@D阿维斯洛——嗯……真正的问题是OP提出的例子(我想)是一个更复杂问题的简化版本,所以……如果我的解决方案能解决(我希望)简化版本,我们不知道(只有OP知道)它是否能解决更复杂的问题。这很好,但在这方面对我没有帮助(或者我不明白),我再次编辑我的帖子,使我的问题更加明显。
class Collection : public ICollection<Component>
{
  public:
    Collection()
    {
      m_comp.push_back(new Component());
      m_comp.push_back(new Component());
    }
    virtual std::vector<Component*> &getComp()
    {
      return m_comp;
    }

  private:
    std::vector<Component*> m_comp;
};
template <typename CompT>
class Collection : public ICollection<CompT>
{
  public:
    Collection()
    {
      m_comp.push_back(new CompT());
      m_comp.push_back(new CompT());
    }
    virtual std::vector<CompT*> &getComp()
    {
      return m_comp;
    }

  private:
    std::vector<CompT*> m_comp;
};
Collection coll;
std::vector<IComponent*>& v = coll.getComp();
Component& comp = *dynamic_cast<Component*>(v[0]);