c ++依赖注入:对象生命周期?

Use*_*ser 9 c++ dependency-injection object-lifetime

我来自C#并试图将我的一些实践翻译成C++.我使用原始指针在我的代码中的各个地方使用了依赖注入.然后我决定用std :: shared_ptr替换原始指针.作为该过程的一部分,有人建议我考虑使用堆栈分配的自动变量而不是动态分配它们(请参阅此问题,尽管该问题是在unique_ptr的上下文中,所以可能会有所不同).

我相信下面的例子显示了自动变量的使用.

class MyClass
{ 
public:
   MyClass(ApplicationService& app): appService_(app)
   {
   }

   ~MyClass()
   {
        appService_.Destroy(something);

   }
private:   
   ApplicationService& appService_;
}

class ConsumerClass
{
    DoSomething()
    {
        CustomApplicationService customAppService;
        MyClass myclass(customAppService);
        myclass...
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,当customAppservice和myclass超出范围时,我如何知道哪个将首先销毁?如果首先销毁customAppService,那么MyClass析构函数将失败.这是在这种情况下使用shared_ptr的一个很好的理由还是有一个干净的方法呢?

UPDATE

ApplicationService是一个类,它是与我的代码使用的第三方库交互所需的全局函数的包装器.我有这个课程,因为我认为它是支持单元测试和存根/模拟自由功能的标准方法.该类只是将调用委托给相应的全局函数.调用appService_.Destroy(something); 实际上是在破坏MyClass的每个特定实例所使用的对象,而不是破坏Application类本身所做的任何操作.

Chr*_*ica 7

答案是:无论如何,你不需要知道,因为你的设计已被打破.

首先,Destroy听起来像一个坏主意,此外如果在一个不负责破坏另一个对象的对象中调用.该Destroy方法的代码属于ApplicationService析构函数(希望是虚拟的,虽然在这种情况下它实际上并不需要),与C#相反,它在完全确定的时间点被调用.

一旦你完成了这个,你将(希望)意识到,MyClass摧毁appService_它并不是它的责任,因为它不拥有它.它ConsumerClass(或更确切地说是DoSomething方法)的责任是真正管理实际服务,并且一旦将Destroy代码移动到析构函数中,它实际上会自动销毁它.RAII如何以干净自动的方式实现一切,这不是很好吗?

class MyClass
{ 
public:
   MyClass(ApplicationService& app): appService_(app)
   {
   }

private:   
   ApplicationService& appService_;
}

class ConsumerClass
{
    DoSomething()
    {
        CustomApplicationService customAppService;
        MyClass myclass(customAppService);
        myclass...
    }
}

class ApplicationService
{
public:
    virtual ~ApplicationService()
    {
        //code from former Destroy method
    }
}

class CustomApplicationService
{
public:
    virtual ~CustomApplicationService()
    {
        //code from former Destroy method
    }
}
Run Code Online (Sandbox Code Playgroud)

这是恕我直言,完美的干净C++方式,这个问题绝对不是垃圾邮件shared_ptr的理由.即使你真的需要一个专门的Destroy方法,并不能移动代码到析构函数(这我想借此作为与得太多设计动机),那么你就还叫Destroy自DoSomething为再次,MyClass的不负责销毁appService_.

编辑:根据你更新(和我的愚蠢忽视的something论点),你的设计似乎确实非常正确(至少如果你不能搞乱改变ApplicationService),抱歉.

尽管类成员应该以相反的构造顺序销毁,但我不确定这也适用于本地自动变量.你可以做些什么来确保以定义的顺序调用析构函数是使用简单的块引入嵌套的作用域:

void DoSomething()
{
    CustomApplicationService customAppService;
    {
        MyClass myclass(customAppService);
        myclass...
    }       // myclass destroyed
}       // customAppService destroyed
Run Code Online (Sandbox Code Playgroud)

当然,仍然完全没有必要使用动态分配,抛开shared_ptrs.尽管嵌套的块稍微破坏了代码,但它并没有反对以非动态的方式应用动态分配的丑陋而且没有任何理由,并且它至少"以语义方式看起来很好",并且customAppService在块的顶部有声明;)