Métodos de encadeamento e variáveis temporárias, por favor esclareça
-
27-09-2019 - |
Pergunta
Cumprimentos a todos!
Tenho uma classe que recebe um ponteiro para um "círculo" (por exemplo) e depois ajusta seus atributos através de alguns métodos de "encadeamento".Algo assim:
class CCircleSetter
{
public:
explicit CCircleSetter( CCirclePtr circle ) : m_circle(circle)
{
}
CCircleSetter & Radius( int radius )
{
if (m_circle) m_circle->SetAttribute( "radius", radius );
return *this;
}
CCircleSetter & Center( CPoint center )
{
if (m_circle) m_circle->SetAttribute( "center", center );
return *this;
}
operator bool() const
{
return ( m_circle != NULL );
}
private:
CCirclePtr m_circle;
};
Agora me pergunto se este código é legal ou não:
if ( CCircleSetter(myCircle).Radius(10).Center(myPoint) )
{ ... }
Por um lado, acho que aquele objeto temporário, criado dentro da expressão "if", viverá até o final desta expressão.Portanto, as chamadas para “Radius” e “Center” são legais.Mas, por outro lado, é um comportamento indefinido usar referências a variáveis temporárias e me parece que estou fazendo exatamente esse tipo de coisa - usando (*this), onde "this" é temporário.Isso me dá algumas dúvidas, então, por favor, esclareça.Obrigado!
Solução
Não, tudo bem neste caso muito específico, porque o temporário será destruído APÓS a execução de toda a linha, mas em geral é muito ruim manter referências a temporários.
Outras dicas
Mesmo que seja uma variável temporária, isso não significa que todos os seus membros sejam temporários.Dentro do escopo do seu objeto temporário, o this
ponteiro e outros membros não são temporários.Seu código está perfeitamente correto.Agora, se você fez algo como:
SomeFunc(&CCircleSetter(myCircle))
isso seria uma referência a uma variável temporária.
Não creio que uma referência a um temporário seja indefinida, é apenas proibida.Além disso, acredito que isso se aplica apenas a argumentos de função.O Visual Studio permitirá que você passe referências a temporários não const no nível de aviso/erro padrão, embora eu saiba que o gcc não o fará.
Pelo que eu sei, isso só é proibido para que os programadores não dêem um tiro no próprio pé ao armazenar uma referência a um temporário que sai do escopo.Considerando que se trata de C++, acho isso bastante estúpido.
Não vejo nenhum problema com o que você está fazendo.
O que você está fazendo é basicamente o mesmo que em
if( istrm >> a >> b ) ...
que é o mesmo que
if( istream.operator>>(a).operator>>(b).operator some_bool_like_type() )
Acho que isso é bom do ponto de vista da usabilidade.(Certamente não há problemas sintáticos/semânticos com isso.)
No entanto, como sempre, a conversão implícita para bool é um pouco desagradável, porque permite a compilação de código inesperado:
if ( CCircleSetter(myCircle).Radius(10) != 10 )