繁体   English   中英

C ++中的依赖注入

[英]Dependency injection in C++

这也是我在MiškoHevery关于依赖注入处理谷歌会谈的评论中提出的一个问题,但它已被埋没在评论中。

我想知道将依赖关系连接在一起的工厂/构建器步骤如何才能在C ++中工作。

即我们有一个依赖于B的A类。构建器将在堆中分配B,在A的构造函数中传递指向B的指针,同时在堆中分配并返回指向A的指针。

谁事后清理? 建造者在完成后清理它是否好? 它似乎是正确的方法,因为在谈话中它说构建器应该设置预期具有相同生命周期的对象,或者至少依赖关系具有更长的生命周期(我也有一个问题)。 我在代码中的意思是:

class builder {
public:
    builder() :
        m_ClassA(NULL),m_ClassB(NULL) {
    }
    ~builder() {
        if (m_ClassB) {
            delete m_ClassB;
        }
        if (m_ClassA) {
            delete m_ClassA;
        }
    }
    ClassA *build() {
        m_ClassB = new class B;
        m_ClassA = new class A(m_ClassB);
        return m_ClassA;
    }
};

现在,如果有一个依赖项预计持续时间超过我们注入的对象的生命周期(比如ClassC就是依赖项)我明白我们应该将构建方法改为:

ClassA *builder::build(ClassC *classC) {
    m_ClassB = new class B;
    m_ClassA = new class A(m_ClassB, classC);
    return m_ClassA;
}

你最喜欢的方法是什么?

这个讲座是关于Java和依赖注入的。

在C ++中,我们尽量传递RAW指针。 这是因为RAW指针没有与之关联的所有权语义。 如果您没有所有权,那么我们不知道谁负责清理对象。

我发现大部分时间依赖注入是通过C ++中的引用完成的。
在极少数情况下,必须使用指针,将它们包装在std :: unique_ptr <>std :: shared_ptr <>中,具体取决于您希望如何管理所有权。
如果您不能使用C ++ 11功能,请使用std :: auto_ptr <>或boost :: shared_ptr <>。

我还要指出,C ++和Java编程风格现在如此不同,以至于将一种语言的风格应用于另一种语言将不可避免地导致灾难。

这很有意思,DI在C ++中使用模板:

http://adam.younglogic.com/?p=146

我认为作者正在做出正确的举动,以至于没有将Java DI翻译成C ++。 值得一读。

我最近被DI虫咬了。 我认为它解决了很多复杂性问题,特别是自动化部分。 我写了一个原型,让你以漂亮的C ++方式使用DI,或者至少我是这么认为的。 您可以在这里查看代码示例: http//codepad.org/GpOujZ79

显然缺少的东西:没有范围,没有绑定到实现的接口。 后者很容易解决,前者,我不知道。

如果有人对代码有任何意见,我将不胜感激。

使用RAII。

将原始指针交给某人与交给他们所有权相同。 如果这不是你想要做的,你应该给他们某种外观,也知道如何清理有问题的对象。

shared_ptr <>可以做到这一点; 其构造函数的第二个参数可以是一个知道如何删除对象的函数对象。

根据我自己的经验,最好有明确的所有权规则。 对于小型具体对象,最好使用直接复制以避免交叉依赖。

有时交叉依赖是不可避免的,并且没有明确的所有权。 例如,(m)A个实例拥有(n)个B实例,某些B实例可以由多个As拥有。 在这种情况下,最好的方法是将引用计数应用于B,类似于COM引用计数。 任何占有B *的函数必须首先增加引用计数,并在释放占有权时减少它。

我也避免使用boost :: shared_ptr,因为它创建了一个新类型(shared_ptr和B *成为两种不同的类型)。 我发现添加方法时会带来更多麻烦。

如果你不能一劳永逸地解决所有权问题,情况会变得复杂。 您只需要在实现中决定依赖项是否可能比它们注入的对象的寿命更长。

我个人会说不:注入依赖关系的对象将在之后清理。 尝试通过构建器执行此操作意味着构建器必须比依赖项和注入它的对象更长寿。 在我看来,这导致了比它解决的问题更多的问题,因为在完成依赖注入的构造之后,构建器不能用于任何更有用的目的。

在C ++中,通常情况下,当你做正确的事情时,在大多数情况下你根本不需要编写析构函数。 您应该使用智能指针自动删除内容。 我认为,构建器看起来不像ClassA和ClassB实例的所有者。 如果您不喜欢使用智能指针,您应该考虑对象的生命周期及其所有者。

您还可以检查FFEAD依赖注入 它为Spring提供了针对JAVA的DI,并且具有非突兀的处理方式。 它还有许多其他重要功能,如内置的AJAX支持,反射,序列化,C ++解释器,C ++业务组件,ORM,消息传递,Web服务,线程池和支持所有这些功能的应用服务器

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM