injecção dependência em C ++

votos
23

Esta também é uma pergunta que eu perguntei em um comentário em um dos de Miško Hevery Google fala que estava lidando com injeção de dependência, mas ele foi enterrado nos comentários.

Eu me pergunto como pode o passo fábrica / Construtor de fiação as dependências juntos podem trabalhar em C ++.

Ou seja, temos uma classe A que depende do B. O construtor irá alocar B na pilha, passar um ponteiro para B no construtor do A ao mesmo tempo, alocando na pilha e retornar um ponteiro para A.

Quem limpa depois? É bom deixar o construtor limpar depois ele é feito? Parece ser o método correto já que na conversa ele diz que o construtor deve objetos de configuração que se espera venham a ter o mesmo tempo de vida ou pelo menos as dependências têm uma vida mais longa (eu também tenho uma pergunta sobre isso). O que quero dizer em código:

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

Agora, se há uma dependência que é esperado para durar mais tempo do que a vida útil do objeto que estamos a injetá-lo em (digamos ClassC é que a dependência) Eu entendo que devemos mudar o método de construção para algo como:

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

Qual é a sua abordagem preferida?

Publicado 09/12/2008 em 15:26
fonte usuário
Em outras línguas...                            


8 respostas

votos
13

Esta conversa é sobre Java e injeção de dependência.

Em C ++ nós tentamos não passar ponteiros RAW ao redor. Isso ocorre porque um ponteiro RAW não têm semântica de propriedade associados. Se você não tem nenhuma propriedade, em seguida, nós não sabemos quem é responsável pela limpeza do objeto.

Acho que a maior parte da injeção de dependência do tempo é feita através de referências em C ++.
Nos raros casos em que você deve usar ponteiros, envolvê-los em std :: unique_ptr <> ou std :: shared_ptr <> , dependendo de como você deseja gerenciar propriedade.
No caso de você não pode usar C ++ 11 recursos, use std :: auto_ptr <> ou boost :: shared_ptr <>.

Também gostaria de salientar que estilos de programação C ++ e Java agora são tão divergentes que a aplicação do estilo de uma língua para a outra, inevitavelmente, levar ao desastre.

Respondeu 09/12/2008 em 15:47
fonte usuário

votos
9

Isso é interessante, DI em C ++ usando modelos:

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

Eu acho que o autor está fazendo os movimentos certos para não traduzir Java DI em C ++ muito literalmente. Vale a pena ler.

Respondeu 23/12/2009 em 02:08
fonte usuário

votos
6

Eu recentemente foi mordido pelo bichinho DI. Eu acho que ele resolve um monte de problemas de complexidade, especialmente a parte automatizada. Eu escrevi um protótipo que permite usar DI de uma forma muito C ++, ou pelo menos eu penso assim. Você pode dar uma olhada no exemplo de código aqui: http://codepad.org/GpOujZ79

As coisas que são, obviamente, faltando: nenhum escopo, nenhuma ligação de interface para implementação. Este último é muito fácil de resolver, o primeiro, eu não tenho nenhuma idéia.

Eu ficaria grato se alguém aqui tem uma opinião sobre o código.

Respondeu 10/05/2010 em 17:39
fonte usuário

votos
3

Use RAII.

Entregando um ponteiro bruto para alguém é o mesmo que entregá-los propriedade. Se isso não é o que você quer fazer é, você deve dar-lhes algum tipo de fachada que também sabe como limpar o objeto em questão.

shared_ptr <> pode fazer isso; o segundo argumento do seu construtor pode ser um objeto de função que sabe como excluir o objeto.

Respondeu 09/12/2008 em 17:40
fonte usuário

votos
2

Baseado em minha própria experiência, é melhor ter regras de propriedade claros. Para objetos concretos pequenos, é melhor usar cópia direta para evitar a dependência cruzada.

Às vezes, a dependência cruz é inevitável, e não há nenhuma propriedade clara. Por exemplo, exemplos B (M) A instâncias próprio (n), e certos casos B pode ser detida por múltiplos Como. Neste caso, a melhor abordagem é a aplicação de contagem de referência para B, na forma semelhante a contagem de referência COM. Todas as funções que tomar posse de B * tem de aumentar a contagem de referência em primeiro lugar, e diminui-lo quando se liberta a posse.

Eu também evitar o uso de boost :: shared_ptr, pois cria um novo tipo (shared_ptr e B * tornar-se dois tipos distintos). Eu achei que ela traz mais dores de cabeça quando eu adiciono métodos.

Respondeu 23/12/2009 em 17:04
fonte usuário

votos
2

Em C ++, normalmente, quando você fez as coisas direito, você não precisa escrever destruidores em tudo na maioria dos casos. Você deve usar ponteiros inteligentes para excluir coisas automaticamente. Eu acho que, construtor não se parece com o proprietário das instâncias ClassA e ClassB. Se você não gosta de usar ponteiros inteligentes, você deve pensar sobre o tempo objetos vida e seus proprietários.

Respondeu 09/12/2008 em 16:14
fonte usuário

votos
2

As coisas ficam complicadas se você não resolver sobre a questão da propriedade uma vez por todas. Você simplesmente tem que decidir em sua aplicação se é possível que as dependências vivem mais do que os objetos que são injetadas.

Pessoalmente, eu diria que não: o objeto no qual a dependência é injetado irá limpar depois. Tentar fazê-lo através do construtor significa que o construtor terá que viver mais tempo do que tanto a dependência e o objeto em que é injetado. Isso faz com que mais problemas do que resolve, na minha opinião, porque o construtor não servir a qualquer propósito mais útil após a construção com a injeção de dependência tenha sido concluída.

Respondeu 09/12/2008 em 15:33
fonte usuário

votos
1

Você também pode verificar a injeção FFEAD Dependência . Ele fornece DI nas linhas de Primavera para JAVA e tem uma forma não-intrusiva de lidar com as coisas. Ele também tem um monte de outras características importantes como embutido Suporte AJAX, Reflexão, serialização, C ++ Interpreter, Componentes de Negócios para C ++, ORM, Messaging, Web-Services, Thread-Piscinas e um servidor de aplicações que suporta todas estas características.

Respondeu 10/08/2010 em 08:31
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more