Sto solo imparando il c ++ (il primo giorno a guardarlo da quando ho fatto un corso estivo di 1 settimana anni fa)
Stavo convertendo un programma su cui sto lavorando in Java in C ++:
#ifndef ADD_H #define ADD_H #define _USE_MATH_DEFINES #include #include 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
Gli errori erano:
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
Sia l’integrazione che la sum sono entrambe funzioni
Ecco il codice Java, più o meno lo stesso:
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/. * © 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/. * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public static interface Evaluatable { public double evaluate(double value); }
Sono sicuro che sia qualcosa di molto semplice
Inoltre, come posso chiamare
getSkewNormal(double skewValue, double x)
Da un file esterno a SkewNormal.h?
In C ++ devi dichiarare le funzioni prima di poterle usare. Nel tuo codice l’ integrate
non viene dichiarata prima del punto della prima chiamata da integrate
. Lo stesso vale per la sum
. Quindi l’errore. O riordinare le definizioni in modo che la definizione della funzione preceda la prima chiamata a quella funzione, oppure introdurre una dichiarazione [forward] non-definente per ciascuna funzione.
Inoltre, definisce funzioni esterne non inline nei file di intestazione in un no-no in C ++. Le tue definizioni di SkewNormalEvalutatable::SkewNormalEvalutatable
, getSkewNormal
, integrate
ecc. Non hanno business nel file di intestazione.
Anche SkewNormalEvalutatable e();
la dichiarazione in C ++ dichiara una funzione e
, non un object e
come sembri supporre. Il semplice SkewNormalEvalutatable e;
dichiarerà un object inizializzato dal costruttore predefinito.
Inoltre, si riceve l’ultimo parametro di integrate
(e di sum
) per valore come object di tipo Evaluatable
. Ciò significa che il tentativo di passare a SkewNormalEvalutatable
come ultimo argomento di integrate
comporterà il SkewNormalEvalutatable
di Evaluatable
a Evaluatable
. Il polimorfismo non funzionerà per questo. Se si desidera un comportamento polimorfico, è necessario ricevere questo parametro per riferimento o per puntatore, ma non per valore.
In C ++, i tuoi file sorgente vengono solitamente analizzati dall’alto verso il basso in un singolo passaggio, quindi qualsiasi variabile o funzione deve essere dichiarata prima di poter essere utilizzata. Ci sono alcune eccezioni a questo, come quando si definiscono le funzioni in linea in una definizione di class, ma non è il caso del codice.
Spostare la definizione di integrate
sopra quella per getSkewNormal
o aggiungere una dichiarazione getSkewNormal
sopra getSkewNormal
:
double integrate (double start, double stop, int numSteps, Evaluatable evalObj);
Lo stesso vale per la sum
.
In generale, le funzioni C ++ devono essere dichiarate prima di chiamarle. Quindi prima della definizione di getSkewNormal()
, il compilatore deve vedere la dichiarazione:
double integrate (double start, double stop, int numSteps, Evaluatable evalObj);
Principalmente ciò che le persone fanno è mettere tutte le dichiarazioni ( solo ) nel file di intestazione e inserire il codice effettivo – le definizioni delle funzioni e dei metodi – in un file sorgente separato ( *.cc
o *.cpp
). Questo risolve in modo chiaro il problema di dover dichiarare tutte le funzioni.