“foo”在此作用域中未声明,C++。

41

我只是在学习C++(自从几年前参加了为期一周的夏令营以来,第一天接触它)

我正在将一个我在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

集成和求和都应该是函数。

这是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/.
 *  &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);
}

我相信这只是一个非常简单的东西

另外,我该如何调用

getSkewNormal(double skewValue, double x)

如何从SkewNormal.h文件外部引用它?


在C++中调用函数之前,您需要先声明它。此外,建议使用M_E而不是2.71828... - Nemo
3个回答

58

在C++中,你必须先声明函数才能使用它们。在你的代码中,integrate 在第一次调用之前没有被声明。同样适用于 sum。因此会出现错误。要么重新排序定义,使函数定义在首次调用该函数之前,要么为每个函数引入一个[前置]非定义声明。

此外,在头文件中定义外部非内联函数在C++中是不允许的。你对 SkewNormalEvalutatable::SkewNormalEvalutatablegetSkewNormalintegrate等的定义不应该在头文件中。

另外,C++中的SkewNormalEvalutatable e();声明将声明一个函数e,而不是像你假设的那样声明一个对象e。简单的 SkewNormalEvalutatable e; 将声明一个由默认构造函数初始化的对象。

此外,你接收 integrate(和 sum )的最后一个参数按值作为Evaluatable类型的对象。这意味着尝试将SkewNormalEvalutatable传递为integrate的最后一个参数将导致SkewNormalEvalutatable被切片为Evaluatable。由于这个原因,多态性不起作用。如果要实现多态行为,必须通过引用或指针而不是值来接收此参数。


1
你可能还可以提到 SkewNormalEvalutatable e(); 是错误的,不会创建任何对象。 - Naveen
太棒了:D 谢谢! 我把它放在一个头文件里, 因为我不确定如何使用多个文件,而头文件似乎更直观。我是否应该再有一个名为“SkewNormal.cpp”的文件,并在那里定义这些函数? - Ryan Amos
@Somanayr:这通常是这样完成的。您将函数的非定义性“声明”放入头文件中。而“定义”则放入.cpp文件中。 - AnT stands with Russia
@Somanayr:好的,你需要将SkewNormal.cpp添加到你的“项目”、“makefile”或者在KDevelop中叫什么就加入什么。 - AnT stands with Russia
@AndreyT 我已经这样做了,但似乎还是不起作用 :/ 这是文件链接:http://pastebin.com/dQ0Kbrna。当我编译时,它告诉我 SkewNormal.h 不存在。感谢迄今为止所有的帮助! - Ryan Amos
显示剩余4条评论

13
在C++中,通常会对源文件进行单遍自上而下的解析,因此任何变量或函数在使用前都必须先声明。当然也有一些例外情况,比如在类定义内联定义函数,但这并不适用于您的代码。
要么将`integrate`的定义移动到`getSkewNormal`的定义之前,要么在`getSkewNormal`上方添加一个前向声明。
double integrate (double start, double stop, int numSteps, Evaluatable evalObj);

对于sum也同样适用。


6

一般情况下,在C++中,函数在调用之前必须先声明。因此,在getSkewNormal()的定义之前,编译器需要看到函数声明:

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

大多数人做的是将所有声明(仅限声明)放在头文件中,并将实际的代码(函数和方法的定义)放入单独的源代码(*.cc或*.cpp)文件中。这样可以很好地解决需要声明所有函数的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接