【问题标题】:Using interface in C++ for dependency injection在 C++ 中使用接口进行依赖注入
【发布时间】:2011-07-31 22:08:51
【问题描述】:

假设我有以下抽象类并将其用作 C++ 中的“接口”:

class IDemo
{
  public:
    virtual ~IDemo() {}
    virtual void Start() = 0;
};


class MyDemo : IDemo
{
  public:
    virtual void start()
    {
      //do stuff
    }
};

然后在需要有接口句柄的类中(通过注入的具体类):

class Project
{
  public:
    Project(IDemo demo);

  private:
    IDemo *_demo;
};

我的意图是通过 Project 的构造函数来分配具体的 Demo 类。此代码无法编译,因为 IDemo 无法实例化。有什么建议? 提前致谢。

【问题讨论】:

    标签: c++ interface dependency-injection abstract-class


    【解决方案1】:

    试试:

     Project::Project(IDemo* demo)
         : _demo(demo)
     {}
    

    但如果演示对象在项目的生命周期内永远不会改变,那么我更喜欢通过引用传递:

    class Project
    {
        public:
            Project(IDemo& d)
              : demo(d)
            {}
        private:
            IDemo&  demo;
    };
    

    然后像这样使用它:

    int main()
    {
        MyDemo    demo;
        Project   project(demo);
    }
    

    【讨论】:

    • @all,首先,浴室休息后得到4个答案真是太神奇了! @Martin,我同意就我而言,通过引用传递更合适。您发现任何使用指针的用例吗?
    • @Icerman:不,永远不应该有使用 RAW 指针的理由。如果你想要动态分配的东西,它应该包含在某种形式的智能指针中(否则没有所有权语义)。
    • 如果传入的内容不是动态分配的怎么办?我可以很容易地创建一个类型并传入它的地址,例如:Demo d;项目项目(&demo)。我正在传递指向演示的指针,但演示不是动态创建的。从听说通过引用存储类变量会导致问题,这似乎是有效的。
    • @user441521:那你按引用传递(这说明生命周期更长,不是动态分配的)。
    • @user441521 我知道这有点晚了,但是整个方案取决于MyDemoIDemo,这不是由于私有继承。所以,它不会按原样工作。
    【解决方案2】:
    Project(IDemo demo);
    

    应该是

    Project(IDemo *demo);
    

    【讨论】:

      【解决方案3】:

      必须是:

      class IDemo
      {
          public:
              virtual ~IDemo() {}
              virtual void Start() = 0;
      };
      
      
      class MyDemo : public IDemo
      {
          public:
              virtual void Start()
              {
                  //do stuff
              }
      };
      
      ...............................
      
      class Project
      {
          public:
              Project(IDemo* demo);
          private:
              IDemo *_demo;
      };
      

      注意

      (1)class MyDemo : public IDemo

      (2) IDemo* demo 之前已经建议过(或者您也可以使用IDemo& demo,但通常使用指向接口的指针)。

      (3) virtual void Start() {...} 而不是 start(标识符区分大小写)。

      【讨论】:

      • 如果你有一些链接,我有兴趣看到这些链接支持使用指针与参考。谢谢,
      • @Icerman:如果您考虑通常的函数和通常的类类型参数,很自然地使用(1)强制输入参数的 const 引用,(2)强制输出参数的非 const 引用,( 3) 可选输入参数的 const 指针(那么你可以传递 0), (4) 可选输出参数的非 const 指针。所有这些都是您愿意在函数调用期间使用的简单参数(即不通过指针存储)。界面是不同的东西。 (见下一条评论)
      • @Icerman:也有传递给函数的具有全部或部分所有权的对象——函数返回后可以使用的对象(接口是对象之王)。将它们作为指针传递是很自然的,以使该指针可以被存储更明确。当然,我们也可以通过引用传递它们,但如果有人要获取地址并存储它,这会更不直观。
      【解决方案4】:

      如果没有看到确切的编译器警告,我建议您更改

      Project(IDemo demo);
      

      Project(IDemo *demo);
      

      【讨论】:

        【解决方案5】:

        这取决于。如果具体的Demo 对象不属于Project,请使用引用:

        class Project
        {
            public:
                Project(IDemo &demo);
            private:
                IDemo &_demo;
        };
        

        如果您想要所有权,请使用boost::shared_ptr

        class Project
        {
            public:
                Project(boost::shared_ptr<IDemo> demo);
            private:
                boost::shared_ptr<IDemo> _demo;
        };
        
        Project project(boost::make_shared<Demo>());
        

        在 C++0x 中,如果您不想共享所有权,也可以使用 std::unique_ptr

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-04
          • 1970-01-01
          • 2012-03-15
          • 2014-10-30
          • 2022-10-09
          • 2023-01-19
          • 1970-01-01
          • 2023-03-23
          相关资源
          最近更新 更多