Alterações na ordem de inicialização do construtor
A ordem de inicialização para construtores de classe foi alterado de Managed Extensions for C++ para Visual C++ 2010.
Comparação da ordem de inicialização do construtor
Em Managed Extensions for C++, a inicialização do construtor ocorreu na seguinte ordem:
O construtor da classe base, se houver, é invocado.
A lista de inicialização da classe é avaliada.
O corpo de código do construtor da classe é executado.
Esta ordem de execução segue as mesmas convenções como na programação do C++ nativa. O novo idioma do Visual C++ prescreve a seguinte ordem de execução para classes CLR:
A lista de inicialização da classe é avaliada.
O construtor da classe base, se houver, é invocado.
O corpo de código do construtor da classe é executado.
Observação que essa alteração só se aplica a classes CLR; classes nativo Visual C++ 2010 ainda seguem convenções anterior. Em ambos os casos, essas regras cascata para cima em toda a cadeia de toda a hierarquia de uma determinada classe.
Considere o seguinte exemplo de código usando Managed Extensions for C++:
__gc class A
{
public:
A() : _n(1)
{
}
protected:
int _n;
};
__gc class B : public A
{
public:
B() : _m(_n)
{
}
private:
int _m;
};
Seguindo a ordem de inicialização do construtor indicadas acima, deveremos ver a seguinte ordem de execução quando novas instâncias da classe B são construídos:
O construtor da classe base A é invocado. O _n membro é inicializado para 1.
A lista de inicialização da classe B é avaliada. O _m membro é inicializado para 1.
O corpo do código da classe B é executado.
Agora, considere o mesmo código em que a nova sintaxe do Visual C++:
ref class A
{
public:
A() : _n(1)
{
}
protected:
int _n;
};
ref class B : A
{
public:
B() : _m(_n)
{
}
private:
int _m;
};
A ordem de execução quando novas instâncias da classe B são construídos sob a nova sintaxe é:
A lista de inicialização da classe B é avaliada. O _m membro é inicializado para 0 (0 é o valor não inicializado a _m membro de classe).
O construtor da classe base A é invocado. O _n membro é inicializado para 1.
O corpo do código da classe B é executado.
Observe que uma sintaxe semelhante produz resultados diferentes para esses exemplos de código. O construtor da classe B depende de um valor de classe base A para inicializar o membro. No entanto, o construtor da classe A ainda não foi invocado. Como uma dependência pode ser especialmente perigosa quando a classe herdada depende de uma alocação de memória ou recursos ocorra no construtor da classe base.
Isso significa que vai de Managed Extensions for C++ 2010 do Visual C++
Em muitos casos as alterações para a ordem de execução dos construtores de classe devem ser transparentes para o programador porque classes base não têm noção do comportamento das classes herdadas. No entanto, como estes exemplos de código ilustram, os construtores de classes herdadas podem ser bastante afetados quando suas listas de inicialização dependem de valores de membros da classe base. Quando você mover seu código de Managed Extensions for C++ para a nova sintaxe, considere a possibilidade de mover tais construções ao corpo do construtor de classe, onde a execução garantida para ocorrer por último.