C返回接口ptr的向量

我正在尝试创建一个返回接口矢量的接口,同时使用它在另一侧实现.

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

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 *.这允许我使用完全实现的Collection和Component.

#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;
};

但是这次我无法使用完整实现的Collection和Component.

当然很容易理解为什么,因为Component *是IComponent *,但严格来说,std :: vector< Component *>不是std :: vector< IComponent *>.此问题也适用于所有模板类型,如迭代器,smart_ptr等…

相反,在Collection :: getComp()中,我必须返回一个std :: vector< IComponent *>.我可以在返回它时投射m_comp(我甚至不确定它是否有效,它不是一个右值?).我还可以存储2个向量,一个Component *和一个IComponent *,并保持它们同步,但这是我认为的丑陋代码.

是否有一些解决方法,或某种我不知道处理它的方式?

更多细节:

我真正想要的是能够在集合中使用Component.如果我将m_comp更改为std :: vector< IComponent *>它将起作用的getComp()返回类型,但我将*使用指向IComponent的指针,而不是指向Collection中的Component.

所以是的,我可以同步两个向量,或者在getComp()中创建一个副本,但我想知道是否有更好的方法.

事件更多细节:

以下是我想如何使用它的示例:
(我只是在Component中添加了getDouble()方法并在Collection中调用它)

#include <iostream>
#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; }
    double getDouble() const { return 3.14; }
};

class Collection : public ICollection
{
  public:
    Collection()
    {
      m_comp.push_back(new Component());
      m_comp.push_back(new Component());
    }
    // Impossible because it does not override the good method
    virtual std::vector<Component*> &getComp()
    {
      std::cout << m_comp[0]->getDouble() << std::endl;
      return m_comp;
    }

  private:
    std::vector<Component*> m_comp;
};

如果我更改了返回类型,Collection将变为:

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

一个解决方案是这样的:

class Collection : public ICollection
{
  public:
    Collection()
    {
      // Useless and redundant code here
      m_comp.push_back(new Component());
      m_icomp.push_back(m_comp.back());
      m_comp.push_back(new Component());
      m_icomp.push_back(m_comp.back());
    }
    // Impossible because it does not override the good method
    virtual std::vector<IComponent*> &getComp()
    {
      std::cout << m_comp[0]->getDouble() << std::endl;
      return m_icomp;
    }

  private:
    // Duplicated storage for "nothing"
    std::vector<Component*> m_comp;
    std::vector<IComponent*> m_icomp;
};

在我看到的回复中,有一些关于实现pop()和push()方法的东西,但在我的项目中我使用的是Map而不是Collection,并且有块的向量.这允许通过执行map [y] [x]来访问块.

问题是存储是固定的.一种解决方案是添加方法getBlock(size_t x,size_t y).但是我希望看到我能用第一种情况做的最好:)

解决方法:

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

不完全是奇怪的重复模板模式,但类似的东西.

我的意思是,像

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

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

所以收藏成了

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

甚至,如果您在模板类中转换Collection

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;
};
上一篇:C游戏设计与多态性问题


下一篇:为什么这种封装破坏在C中起作用?