c++;依赖注入:对象生命周期? 我是从C语言来的,并试图把我的一些实践转化成C++。在整个代码中,我使用原始指针在不同的地方使用了依赖项注入。然后我决定用std::shared_ptr替换原始指针。作为该过程的一部分,建议我考虑使用堆栈分配的自动变量而不是动态分配它们(尽管这个问题是在UnQuyQPTR的上下文中,所以可能不同)。

c++;依赖注入:对象生命周期? 我是从C语言来的,并试图把我的一些实践转化成C++。在整个代码中,我使用原始指针在不同的地方使用了依赖项注入。然后我决定用std::shared_ptr替换原始指针。作为该过程的一部分,建议我考虑使用堆栈分配的自动变量而不是动态分配它们(尽管这个问题是在UnQuyQPTR的上下文中,所以可能不同)。,c++,dependency-injection,object-lifetime,C++,Dependency Injection,Object Lifetime,我相信下面的例子展示了自动变量的使用 class MyClass { public: MyClass(ApplicationService& app): appService_(app) { } ~MyClass() { appService_.Destroy(something); } private: ApplicationService& appService_; } class ConsumerCla

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

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

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

   }
private:   
   ApplicationService& appService_;
}

class ConsumerClass
{
    DoSomething()
    {
        CustomApplicationService customAppService;
        MyClass myclass(customAppService);
        myclass...
    }
}
在上面的示例中,当customAppservice和myclass超出范围时,我如何知道哪个将首先被销毁?如果首先销毁customAppService,MyClass析构函数将失败。这是在这种情况下使用shared_ptr的一个很好的理由,还是有一种干净的解决方法

更新


ApplicationService是一个类,它是与代码使用的第三方库交互所需的全局函数的包装器。我有这个类,因为我相信它是支持单元测试和独立函数的存根/模拟的标准方法。此类仅将调用委托给相应的全局函数。调用appService.Destroy(某物);实际上是销毁MyClass的每个具体实例所使用的对象,而不会破坏应用程序类本身的任何东西。C++中的

< P>,对象通常按照与它们创建的顺序正好相反的顺序销毁。

根据您的示例,
MyClass
将在
CustomApplicationService

例外情况是显式调用析构函数。然而,我认为你不应该在这个阶段担心这个例外

另一个微妙之处叫做。但是,这不适用于自动(堆栈)变量

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

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

   }
private:   
   ApplicationService& appService_;
}

class ConsumerClass
{
    DoSomething()
    {
        CustomApplicationService customAppService;
        MyClass myclass(customAppService);
        myclass...
    }
}
编辑:
来自C++2003-寻找“反向顺序”

6.6.0.2

On exit from a scope (however accomplished), destructors (12.4) are called for all 
constructed objects with automatic storage duration (3.7.2) (named objects or 
temporaries) that are declared in that scope, in the reverse order of their
declaration. ... [Note: However, the program can be terminated (by calling exit()
or abort()(18.3), for example) without destroying class objects with automatic
storage duration. ]

答案是:你不需要知道,因为你的设计被破坏了

首先,
销毁
听起来是个坏主意,而且如果调用的对象对另一个对象的销毁没有责任。
Destroy
方法中的代码属于
ApplicationService
的析构函数(希望它是虚拟的,尽管在本例中它实际上不需要),与C相比,它在完全确定的时间点被调用

完成此操作后,您将(希望)意识到,
MyClass
没有责任销毁
appService\uuuu
,因为它并不拥有它。这是
ConsumerClass
(或者更确切地说是
DoSomething
方法)的责任,它真正管理实际服务,并且在您将
Distroy
的代码移动到析构函数中后,它确实会自动销毁它。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
    }
}
这是一个完美的干净的C++方式,这个问题肯定不是垃圾邮件的一个原因。即使您确实需要一个专用的
Destroy
方法,并且无法将代码移动到析构函数中(我认为这是过度思考设计的动机),那么您仍然会从
DoSomething
调用
Destroy
,同样,MyClass不负责销毁appService

编辑:根据您的更新(以及我愚蠢地忽略了
something
参数),您的设计看起来确实非常正确(至少如果您不能更改
应用程序服务
),对不起

尽管类成员应该按照与构造相反的顺序被销毁,但我不确定这是否也适用于局部自动变量。要确保以定义的顺序调用析构函数,可以使用简单块引入嵌套作用域:

void DoSomething()
{
    CustomApplicationService customAppService;
    {
        MyClass myclass(customAppService);
        myclass...
    }       // myclass destroyed
}       // customAppService destroyed

当然,仍然完全没有必要使用动态分配,更不用说
shared\u ptr
s了。尽管嵌套块有点破坏了代码,但它并不反对以非动态方式毫无理由地应用动态分配的丑陋性,它至少“在语义上看起来不错”,在块的顶部有
customAppService
的声明;)

它是按相反顺序破坏的特定实例的子对象。你确定在这种情况下情况也是相反的吗?任何引用都会有帮助的,绝对。如果MyClass包含子对象,它们将在调用CustomApplicationService析构函数之前被完全销毁。我相信Chris是正确的,但如果我真的想确定(而不是信任对规范的解释),我会将MyClass对象放入它自己的作用域中,{MyClass MyClass(…);…}然后我知道物体先消失了。事实上,这句话的标准证明会很好。我知道它对于成员变量,但也适用于局部变量?这个C++ FAQ说这是正确的:虽然它不引用一个规范。我知道从我的例子中看不出它是自明的,但是MyClass并没有破坏AppService。请看我的更新。@User啊,对不起,我这个笨蛋翻了那个
什么
参数。不用担心,您没有完整的上下文。我相信这在技术上是可行的,但我想知道维护&创建脆弱代码的可能性&代码是否传达了意图。我想我宁愿使用共享的ptr,也不愿依赖于不明显的破坏行为。它让我想起构造函数初始化列表中依赖项的顺序(对象是如何按照声明的相同顺序初始化的)。当我读到人们谈论依赖这个事实时,我觉得这真的很脆弱。但如果这是最好的方法,那么我会考虑这样做。@用户有明确的块,你可以完全确定,它不使用任何“易碎”。