C++
Home

Construtores Explicit

- Não se esqueça que:

Qualquer construtor que é chamado com um argumento pode ser usado pelo compilador para executar uma conversão implícita, na qual o tipo recebido pelo construtor é convertido em um objeto da classe na qual o construtor está definido. A conversão é automatica e o programador não usar um operador de coerção.

Em alguns lugares, quando o compilador faz isso pode gerar problemas, ou mesmo o programador não quer que isso aconteça.

Exemplo de Coerção executada pelo compilador:

#include <iostream>

using std::ostream;
using std::cout;

#include <cassert>

class Array {
   friend ostream & operator<<( ostream &, const Array & );

public:
   Array( int ); // construtor defaut
   ~Array(); // destruidor

private:
   int size;
   int *ptr;
};

Array::Array( int vsize = 10 )
{
   size = ( vsize > 0 ? vsize : 10 );
   cout << "Construtor chamado para " << size << " elementos " << std::endl;

   // alocação
   ptr = new int[size];
   assert( ptr != 0 );

   // inicia array
   for ( int i=0; i<size; i++ )
   {   
      ptr[i] = 0;
   }   
}

Array::~Array()
{
   delete [] ptr;
}

ostream & operator<<( ostream &output, const Array &varray )
{
   int i=0;

   for ( i=0; i<varray.size; i++ )
   {   
      cout << varray.ptr[i] << std::endl;
   }

   return output;
}

void outputArray( const Array & );

int main()
{

   // iniciamos um com 7 elementos
   Array vinteger( 7 );

   // envia o array para a função que recebe array
   outputArray( vinteger );

   // envia o int para a função que recebe Array
   // como a função receberia um Array e não um int
   // o compilador verifica qual o tipo do construtor de array
   // como o construtor de array é int, ele recebe o argumento e executa o
   // construtor

   outputArray( 15 );

   return 0;
}

void outputArray( const Array &aimprimir )
{
   cout << "O array recebido contem "<< aimprimir << std::endl;
}

Para evitar essa execução, devemos usar o operador explicit.

Um construtor que é declarado como explicit não pode ser usado para conversão implícita.

class Array {
   friend ostream & operator<<( ostream &, const Array & );

public:
   explicit Array( int ); // construtor defaut
   ~Array(); // destruidor

private:
   int size;
   int *ptr;
};

Usando o exemplo anterior, o erro aprensetado pelo compilador será

error C2664: 'outputArray' : cannot convert parameter 1 from 'const int' to 'const class Array &'
Reason: cannot convert from 'const int' to 'const class Array'
No constructor could take the source type, or constructor overload resolution was ambiguous