O Autocast do compilador do Visual Studio 2008 não é dobrado com o SQRT no C ++?
Pergunta
O compilador não deve ser lançado automaticamente para um dobro a seguir? Pelo menos de acordo com Walter Savitch.
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int k;
for(k = 1; k <= 10; k++)
cout << "The square root of k is: " << sqrt(k) << endl;
return 0;
}//error C2668: 'sqrt' : ambiguous call to overloaded function
//Visual Studio 2008 on Win Vista
Solução
O problema é que existem três versões de sqrt
escolher a partir de:
double sqrt ( double x );
float sqrt ( float x );
long double sqrt ( long double x );
Desde que você está passando em um int
, o compilador promoverá seu argumento, mas é igualmente válido promover seu número inteiro a qualquer um dos tipos acima, por isso é ambíguo.
Você pode consertar isso simplesmente lançando explicitamente para um dos tipos acima, como em:
cout << "The square root of k is: " << sqrt((double)k) << endl;
Outras dicas
O erro ambíguo de chamada é que ele não sabe qual função chamar não é que não seja implicitamente convertendo.
Veja o seguinte. Se eu criar minha própria função que pega um dobro e retorna um dobro, não tem problema em conversão implicitamente. Como seu número inteiro pode ser convertido para qualquer uma das três sobrecargas, ele não sabe como ligar.
double mysqrt(double d)
{
return d;
}
using namespace std;
int main(int argc, char ** argv)
{
int k;
for(k = 1; k <= 10; k++)
cout << "The square root of k is: " << mysqrt(k) << endl;
return 0;
}//Works Fine
No entanto, se eu adicionar outra versão do MySQRT que leva um flutuador, crio um erro ambíguo de chamada.
double mysqrt(float f)
{
return f;
}
double mysqrt(double d)
{
return d;
}
using namespace std;
int main(int argc, char ** argv)
{
int k;
for(k = 1; k <= 10; k++)
cout << "The square root of k is: " << mysqrt(k) << endl;
return 0;
}//error C2668: 'mysqrt' : ambiguous call to overloaded function
Já que existem múltiplos Funções SQRT (sobrecarga) e mais de 1 pode aceitar um int como um parâmetro sem perder a precisão, cabe a você especificar qual (e isso é uma coisa boa, porque você não deseja que o compilador toma decisões para você com base em evidências 'circunstanciais' - passando um int para sqrt).
C sempre retorna a versão dupla, a menos que o SQRTF seja chamado.
Tente lançar sua ligação com (duplo)
Do msdn: [
double sqrt(
double x
);
float sqrt(
float x
); // C++ only
long double sqrt(
long double x
); // C++ only
float sqrtf(
float x
);
]1
Existem várias sobrecargas no std :: sqrt no cmath. Um leva um flutuador e outro leva um dobro. O compilador não pode saber qual você deseja ser chamado e o INTS pode ser lançado em qualquer um deles.
Na ausência de sobrecargas adicionais, ele foi lançado automaticamente para dobrar [este é o caso em C] como você espera.
Sim, ele deve ser lançado automaticamente de int para o dobro. G ++ compila essa multa, então eu acho que vs está errado
EDIT: Não sei por que a resposta do MO é votada. Mas acho que durante a sobrecarga de função no C ++, a conversão automática deve sempre acontecer com um tipo de dados mais alto na conversão automática. Para Ex: Se houver uma opção para converter para Long, Float e Double, ele sempre deve fazer uma conversão INT para dobrar.
Eu tentei isso no G ++ e está chamando a função SQRT (dupla).
#include <iostream>
#include <cmath>
#include <typeinfo>
using namespace std;
int main(){
int k;
for(k = 1; k <= 10; k++)
cout << "The square root of k is: " << sqrt(k) <<' '<< typeid(sqrt(k)).name()<< endl;
return 0;
}
Portanto, a saída do typeId () é "D", o que significa que fez uma conversão automática de int para o dobro.