‘foo’ не была объявлена в этой области c

#c #function

#c #функция

Вопрос:

Я только изучаю c (первый день, когда я изучаю его с тех пор, как я провел 1 неделю в летнем лагере много лет назад)

Я конвертировал программу, над которой я работаю на Java, в 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
  

Ошибки были:

 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
  

Предполагается, что Integrate и sum являются функциями

Вот код Java, более или менее такой же:

 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/.
 *  amp;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/.
 *  amp;copy; 2001 Marty Hall and Larry Brown;
 *  may be freely used or adapted. 
 */
public static interface Evaluatable {
      public double evaluate(double value);
}
  

Я уверен, что это что-то очень простое

Кроме того, как мне вызвать

 getSkewNormal(double skewValue, double x)
  

Из файла за пределами SkewNormal.h?

Комментарии:

1. Вам нужно объявить функцию, прежде чем вы сможете вызвать ее на C . Кроме того, предпочитаю M_E 2.71828...

Ответ №1:

В C предполагается, что вы объявляете функции, прежде чем сможете их использовать. В вашем коде integrate не объявлена до момента первого вызова integrate . То же самое относится к sum . Отсюда и ошибка. Либо измените порядок ваших определений таким образом, чтобы определение функции предшествовало первому вызову этой функции, либо введите [forward] неопределяющее объявление для каждой функции.

Кроме того, определение внешних нестрочных функций в файлах заголовков в C запрещено. Ваши определения SkewNormalEvalutatable::SkewNormalEvalutatable , getSkewNormal integrate и т.д. Не имеют отношения к заголовочному файлу.

Также SkewNormalEvalutatable e(); объявление в C объявляет функцию e , а не объект e , как вы, кажется, предполагаете. Простой SkewNormalEvalutatable e; объявит объект, инициализированный конструктором по умолчанию.

Кроме того, вы получаете последний параметр integrate (и of sum ) по значению как объект Evaluatable типа. Это означает, что попытка передать SkewNormalEvalutatable в качестве последнего аргумента integrate приведет к SkewNormalEvalutatable разделению на Evaluatable . Из-за этого полиморфизм работать не будет. Если вы хотите полиморфное поведение, вы должны получить этот параметр по ссылке или указателю, но не по значению.

Комментарии:

1. Вероятно, вы также можете упомянуть, что SkewNormalEvalutatable e (); это неправильно и не создаст никаких объектов.

2. Потрясающе: D Спасибо! Я поместил ее в файл заголовка, потому что я не был уверен, как использовать несколько файлов, и заголовок казался более простым. Должен ли у меня быть другой файл с именем «SkewNormal.cpp » и определите функцию там?

3. @Somanayr: Вот как это обычно делается. Вы помещаете неопределяющие объявления ваших функций в файл заголовка. Определения отправляются в файл .cpp.

4. Не возражаете, если я задам еще один вопрос? Мой main.cpp файл ( pastie.org/private/oifaxdkebrsi1oqofn0ea ) выдает мне ошибку при компиляции: main.cpp: 7: неопределенная ссылка на ‘getSkewNormal(double, удвоение)’. Не могли бы вы рассказать мне, в чем дело и как это исправить? Я переместил функции в SkewNormal.cpp ( pastie.org/private/4n8cys2zpr2bfw3brucsg ) и просто объявления в SkewNormal.h ( pastie.org/private/1g7c66xjfd3qu6idfxmwa )

5. @Somanayr: Теперь ваша программа состоит из двух исходных файлов — main.cpp и SkewNormal.cpp . Вы должны скомпилировать оба файла и связать результаты (файлы объектов) вместе. Вы, по-видимому, либо вообще не компилируете SkewNormal.cpp , либо не связываете результат его компиляции с окончательной программой. Какой компилятор вы используете?

Ответ №2:

В C ваши исходные файлы обычно анализируются сверху вниз за один проход, поэтому любая переменная или функция должны быть объявлены, прежде чем их можно будет использовать. Из этого есть некоторые исключения, например, при определении функций, встроенных в определение класса, но это не относится к вашему коду.

Либо переместите определение integrate выше определения для getSkewNormal , либо добавьте прямое объявление выше getSkewNormal :

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

То же самое относится к sum .

Ответ №3:

В общем, в C функции должны быть объявлены перед их вызовом. Поэтому за некоторое время до определения getSkewNormal() компилятору необходимо просмотреть объявление:

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

В основном, что люди делают, это помещают все объявления (только) в файл заголовка и помещают фактический код — определения функций и методов — в отдельный исходный ( *.cc или *.cpp ) файл. Это аккуратно решает проблему необходимости объявления всех функций.