This annotated version has comments on all three files, but only for what is new in this program.
// fut.h
//
// Binomial futures option pricing model: declarations
//
#define MAXTERNODES 40 

struct valhedge {
  double value;
  double delta;};
  ^
  |
  The new data type valhedge allows us to return the value and
  the hedge ratio in one object.  A messier solution is to
  return values in the arguments or in locations pointed to by
  the arguments.

class fut {
public:
  fut(double ttm=.25,int npers=4,double r=.05,double sigma=.3);
  valhedge eurcall(double f0,double X);
  ^
  |
  This function returns the value and hedge ration for a European
  call option on a futures price.

private:
  int nper;
  double tinc,r1per,disc,disctm,up,down,pratio,prcup,prcdn;
  double val[MAXTERNODES];};



// futtest.cc
//
// Binomial futures option pricing model: test
//
#include <iostream.h>
#include "fut.h"
main() {
  fut c1;
  valhedge x;
  ^
  |
  This is the declaration of an object x of type valhedge, that
  includes both the value and the hedge ratio.  The result of
  call pricing will be stored here temporarily and its components
  will be printed separately.

  double futprice,strikeP;
  cout << "\nType the futures price, a space, the strike"
    << " price, and then ENTER.\n"
    << "Make the futures price negative to terminate." << "\n\n";
  while(1) {
    cout << "futures-price strike-price: ";
    cin >> futprice >> strikeP;
    if(futprice < 0.0) {
      cout << endl;
      return(0);}
    if(!cin) {
      cout << "invalid input" << endl;
      return(1);}
    x = c1.eurcall(futprice,strikeP);
    ^
    |
    The results of eurcall are temporarily stored here...

    cout << "call option value = " << x.value << "\n"
                                      ^
                                      |
                                      ... and printed here...

      << "hedge (number of contracts) = " << x.delta
                                             ^
                                             |
                                             ... and here.

      << "\n\n";}}


// fut.cc
//
// Binomial futures option pricing model: implementation
//
#include <math.h>
#include "fut.h"
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
fut::fut(double ttm,int npers,double r,double sigma) {
  nper = npers;
  tinc = ttm/(double) nper;
  r1per = exp(r * tinc);
  disc = 1.0/r1per;
  disctm = exp(-r * ttm);
  up = 1.0 + sigma * sqrt(tinc);
  ^
  |
  Since the futures requires no initial investment, there is
  no interest returned.

  down = 1.0 - sigma * sqrt(tinc);
  prcup = 0.5*disc;
  prcdn = 0.5*disc;}

valhedge fut::eurcall(double f0,double X) {
  int i,j;
  double futprice;
  valhedge x1;
  ^
  |
  This declares the variable x1 in which we will store the
  result to be returned.

// initialize terminal payoffs
// i is the number of up moves over the whole life
  for(i=0;i<=nper;i++) {
    futprice = f0 * pow(up,(double) i) * pow(down,(double) (nper-i));
    val[i] = MAX(futprice - X,0);}
// compute prices back through the tree
// j+1 is the number of periods from the end
// i is the number of up moves from the start
  for(j=0;j<nper-1;j++) {
    for(i=0;i<nper-j;i++) {
      val[i] = prcdn * val[i] + prcup * val[i+1];}}
  ^
  |
  This for loop (over j) does all of the steps except the actual valuation
  at the beginning, which is done separately afterwards, since we need
  to know val one period from the end to compute the hedge as well
  as the value.

  x1.value = prcdn * val[0] + prcup * val[1];
  ^
  |
  This computes the value at the initial node...

  x1.delta = (val[1]-val[0]) / (f0*(up-down));
  ^
  |
  ... and this computes the hedge ratio.

  return(x1);}
  ^
  |
  An object of type valhedge is returned just like an object of a
  built-in type like double or int.