C++ Type Casting – 3ª e ultima parte

No post anterior vimos como realizar as operações de casting usando os novos operadores do C++, neste post vamos ver como realizar casting com os smart pointers da Boost , estes operadores podem ser usados com o shared_ptr e o intrusive_ptr.

Mas primeiramente, porque existem operadores de cast específicos da Boost? Pelo fato de que os operadores do C++ não estão preparados para lidar com smart pointers e contagem de referências, dessa forma, caso se utilize um operador padrão do C++ a contagem de referência do objeto pode se tornar invalida, resultando em um objeto sendo destruído mais de uma vez. Exemplo:


enum Eventos_e
{
    TIRO,
    ABRIR_PORTA
};

class Objeto
{
    public:
        virtual void Evento(int tipo, void *param) = 0;
        virtual void Atualizar()=0;
};

class Monstro: public Objeto
{
    public:
        virtual void Evento(int tipo, void *param);
        virtual void Atualizar();
       
    private:
        int m_energia;
};

Com base na hierarquia acima, vamos criar alguns objetos e fazer um cast:


int main(int, char **)
{
    using namespace boost;

    shared_ptr<Objeto> obj(new Monstro());
   
    shared_ptr<Monstro> monstro(static_cast<Monstro *>(obj.get()));   
}

Repare que na linha onde é feito o cast é usado o método get do shared_ptr para se obter uma referência ao objeto que obj armazena, depois é feito o cast e o ponteiro resultante é utilizado para inicializar o ponteiro “monstro”, note que monstro foi inicializado com um ponteiro comum, não com outro shared_ptr, ou seja, para o shared_ptr “monstro” ninguém até o momento gerenciava esse ponteiro, então ele vai simplesmente começar uma nova contagem de referências, dessa forma, quando a função terminar de executar, ambos os smart pointers vão destruir o objeto Monstro, resultando em um comportamento indefinido.

Para evitar esses problemas foram criados os casts a seguir:

Cada um dos casts acima deve ser usado nas mesmas situações dos casts do C++, a diferença é que eles devem ser apenas usados quando os objetos envolvidos são gerenciados por smart pointers.

No caso do exemplo anterior, o código correto é listado abaixo:


int main(int, char **)
{
    using namespace boost;

    shared_ptr<Objeto> obj(new Monstro());
   
    shared_ptr<Monstro> monstro(static_pointer_cast<Monstro>(obj)));   
}

Note que as operações de cast da boost são idênticas as do C++, a diferença é o nome do operador usado.

As operações de cast da Boost devem ser sempre usadas quando é necessário fazer casts entre ponteiros gerenciados por smart pointers da mesma, nos outros casos, deve-se utilizar os operadores do C++.

5 Respostas para “C++ Type Casting – 3ª e ultima parte”

  1. skhaz Disse:

    O mesmo ocorre quando se usa mem_fun da std com shared_ptrs, em alguns compiladores mais modernos é possivel usar o mem_fun, mais em alguns é nescessario usar o mem_fn da boost
    Otimo Artigo!

  2. bcsanches Disse:

    É verdade, bom que ja fica anotado para os leitores!

    Obrigado skhaz!

  3. Murilo Adriano Disse:

    Cara, li alguns posts seus e estão muito legais!
    Parabéns ae!

    Abraço.

  4. Bruno Sanches Disse:

    Obrigado Murilo!

  5. Caloni.com.br » Blog Archive » Últimas pesquisas na blogosfera nacional Disse:

    [...] Os diversos tipos de casting [...]

Deixe uma resposta