2011-06-08 16 views
28

Estoy aprendiendo C++ (primer día mirándolo desde que tomé hace 1 semana de campamento de verano años)'foo' no fue declarado en este ámbito C++

me estaba convirtiendo un programa que estoy trabajando en Java a C++:

#ifndef ADD_H 
#define ADD_H 
#define _USE_MATH_DEFINES 
#include <iostream> 
#include <math.h> 

using namespace std; 

class Evaluatable { 
public: 
    virtual double evaluate(double x); 
}; 

class SkewNormalEvalutatable : Evaluatable{ 
public: 
    SkewNormalEvalutatable(); 
    double evaluate(double x){ 
    return 1/sqrt(2 * M_PI) * pow(2.71828182845904523536, -x * x/2); 
    } 
}; 

SkewNormalEvalutatable::SkewNormalEvalutatable() 
{ 
} 

double getSkewNormal(double skewValue, double x) 
{ 
    SkewNormalEvalutatable e(); 
    return 2/sqrt(2 * M_PI) * pow(2.71828182845904523536, -x * x/2) * integrate(-1000, skewValue * x, 10000, e); 
} 

// double normalDist(double x){ 
// return 1/Math.sqrt(2 * Math.PI) * Math.pow(Math.E, -x * x/2); 
// } 

double integrate (double start, double stop, 
            int numSteps, 
            Evaluatable evalObj) 
{ 
    double stepSize = (stop - start)/(double)numSteps; 
    start = start + stepSize/2.0; 
    return (stepSize * sum(start, stop, stepSize, evalObj)); 
} 

double sum (double start, double stop, 
           double stepSize, 
           Evaluatable evalObj) 
{ 
    double sum = 0.0, current = start; 
    while (current <= stop) { 
    sum += evalObj.evaluate(current); 
    current += stepSize; 
    } 
    return(sum); 
} 

// int main() 
// { 
// cout << getSkewNormal(10.0, 0) << endl; 
// return 0; 
// } 
#endif 

Los errores fueron:

SkewNormal.h: In function 'double getSkewNormal(double, double)' : 
SkewNormal.h: 29: error: 'integrate' was not declared in this scope 
SkewNormal.h: In function 'double integrate(double, double, int, Evaluatable)': 
SkewNormal.h:41: error: 'sum' was not declared in this scope 

integrar y suma se supone tanto a ser funciones

Este es el código de Java, más o menos lo mismo:

public static double negativelySkewed(double skew, int min, int max){ 
    return randomSkew(skew) * (max - min) + min; 
} 

public static double randomSkew(final double skew){ 
    final double xVal = Math.random(); 
    return 2 * normalDist(xVal) * Integral.integrate(-500, skew * xVal, 100000, new Evaluatable() { 

     @Override 
     public double evaluate(double value) { 
      return normalDist(value); 
     } 
    }); 
} 

public static double normalDist(double x){ 
    return 1/Math.sqrt(2 * Math.PI) * Math.pow(Math.E, -x * x/2); 
} 

/** A class to calculate summations and numeric integrals. The 
* integral is calculated according to the midpoint rule. 
* 
* Taken from Core Web Programming from 
* Prentice Hall and Sun Microsystems Press, 
* http://www.corewebprogramming.com/. 
* &copy; 2001 Marty Hall and Larry Brown; 
* may be freely used or adapted. 
*/ 

public static class Integral { 
    /** Returns the sum of f(x) from x=start to x=stop, where the 
    * function f is defined by the evaluate method of the 
    * Evaluatable object. 
    */ 

    public static double sum(double start, double stop, 
          double stepSize, 
          Evaluatable evalObj) { 
    double sum = 0.0, current = start; 
    while (current <= stop) { 
     sum += evalObj.evaluate(current); 
     current += stepSize; 
    } 
    return(sum); 
    } 

    /** Returns an approximation of the integral of f(x) from 
    * start to stop, using the midpoint rule. The function f is 
    * defined by the evaluate method of the Evaluatable object. 
    */ 

    public static double integrate(double start, double stop, 
           int numSteps, 
           Evaluatable evalObj) { 
    double stepSize = (stop - start)/(double)numSteps; 
    start = start + stepSize/2.0; 
    return(stepSize * sum(start, stop, stepSize, evalObj)); 
    } 
} 

/** An interface for evaluating functions y = f(x) at a specific 
* value. Both x and y are double-precision floating-point 
* numbers. 
* 
* Taken from Core Web Programming from 
* Prentice Hall and Sun Microsystems Press, 
* http://www.corewebprogramming.com/. 
* &copy; 2001 Marty Hall and Larry Brown; 
* may be freely used or adapted. 
*/ 
public static interface Evaluatable { 
     public double evaluate(double value); 
} 

Estoy seguro de que es algo muy simple

Además, ¿cómo me llamo

getSkewNormal(double skewValue, double x) 

Desde un archivo fuera SkewNormal .h?

+0

Debe declarar una función antes de poder llamarla en C++. Además, prefiera 'M_E' a' 2.71828 ... ' – Nemo

Respuesta

42

En C++ se supone que debe declarar funciones antes de poder usarlas. En su código integrate no se declara antes del punto de la primera llamada al integrate. Lo mismo se aplica al sum. De ahí el error. Reordene sus definiciones para que la definición de la función preceda a la primera llamada a esa función o introduzca una declaración [forward] no definitoria para cada función.

Además, define funciones externas no en línea en archivos de encabezado en un no-no en C++. Sus definiciones de SkewNormalEvalutatable::SkewNormalEvalutatable, getSkewNormal, integrate etc. no tienen ningún sentido comercial en el archivo de encabezado.

También SkewNormalEvalutatable e(); declaración en C++ declara una función e, no es un objeto e como parece suponer. El simple SkewNormalEvalutatable e; declarará un objeto inicializado por constructor predeterminado.

Además, recibirá el último parámetro de integrate (y de sum) por valor como un objeto de tipo Evaluatable. Eso significa que intentar pasar SkewNormalEvalutatable como último argumento de integrate dará como resultado que SkewNormalEvalutatable se corte a Evaluatable. El polimorfismo no funcionará por eso. Si desea un comportamiento polimórfico, debe recibir este parámetro por referencia o por puntero, pero no por valor.

+1

También puede mencionar que' SkewNormalEvalutable e(); 'es incorrecto y no creará ningún objeto. – Naveen

+0

Impresionante: D ¡Gracias! Lo puse en un archivo de cabecera porque no estaba seguro de cómo usar varios archivos y el encabezado parecía más sencillo. ¿Debo tener otro archivo llamado "SkewNormal.cpp" y definir la función allí? –

+0

@Somanayr: así es como normalmente se hace. Pones * declaraciones * que no definen * tus funciones en el archivo de encabezado. Las * definiciones * entran en el archivo .cpp. – AnT

5

En general, en C++ las funciones deben declararse antes de llamarlas. Así que en algún momento antes de la definición de getSkewNormal(), el compilador necesita ver la declaración:

double integrate (double start, double stop, int numSteps, Evaluatable evalObj); 

Parcialmente lo que se hace es poner todas las declaraciones (única) en el archivo de cabecera, y poner el código real - la definiciones de las funciones y métodos - en un archivo de origen separado (*.cc o *.cpp). Esto resuelve el problema de necesitar todas las funciones para ser declaradas.

7

En C++, los archivos de origen generalmente se analizan de arriba a abajo en una sola pasada, por lo que cualquier variable o función debe declararse antes de que se puedan usar.Hay algunas excepciones a esto, como cuando se definen funciones en línea en una definición de clase, pero ese no es el caso para su código.

Mueva la definición de integrate por encima de la otra para getSkewNormal, o añadir una declaración hacia adelante por encima de getSkewNormal:

double integrate (double start, double stop, int numSteps, Evaluatable evalObj); 

Lo mismo se aplica para sum.

Cuestiones relacionadas