0

I have a class implemented in a .cpp file as follow :

#include <ctime>
#include <iostream>

// les 3 lib boost/random nécessaire a généré les radiuses
#include "boost/random/mersenne_twister.hpp"
#include "boost/random/normal_distribution.hpp"
#include "boost/random/variate_generator.hpp"
// la lib boost fournissant des arrays multidimensionnels
#include "boost/multi_array.hpp"

#include "porenetwork.h"

using namespace std;

typedef boost::random::mt19937 ENG;
typedef boost::normal_distribution<double> DIST;   // Normal Distribution
typedef boost::variate_generator<ENG,DIST> GEN;    // Variate generator

typedef boost::multi_array<bool, 3> StateNetworkType;
typedef boost::multi_array<double, 3> RadiusNetworkType;
typedef StateNetworkType::index index;
typedef boost::multi_array_types::index_range range;



PoreNetwork::PoreNetwork(int esize)
{
cout << "esize = " << esize << endl;
Size = esize;
StateNetworkType States(boost::extents[Size][Size][Size]);
RadiusNetworkType Radiuses(boost::extents[Size][Size][Size]);

// initialise the Radiuses
ENG eng;
eng.seed(static_cast<unsigned int>(std::time(0)));
DIST dist(0,1);
GEN gen(eng, dist);

for(index i = 0; i != Size; ++i) 
    for(index j = 0; j != Size; ++j)
        for(index k = 0; k != Size; ++k)
            Radiuses[i][j][k] = gen();

}

int PoreNetwork::getSize() {return Size;}

And defined in a header .h file as follow :

#ifndef PORENETWORK_H
#define PORENETWORK_H

#include "boost/multi_array.hpp"

typedef boost::multi_array<bool, 3> StateNetworkType;
typedef boost::multi_array<double, 3> RadiusNetworkType;

class PoreNetwork
{
public:
    PoreNetwork(int esize);
    int getSize();
    StateNetworkType States;
    RadiusNetworkType Radiuses;

private:
    int Size;
    /* add your private declarations */
};

#endif /* PORENETWORK_H */ 

My problem is that the Attributes PoreNetwork::Radiuses and PoreNetwork::States do not seem to get initialized when I call this from my main.cpp.

As I understand it, the Radiuses and States in my .cpp are not the ones defined in my headers file because I re-define them.

My problem is : how do I define and initialize these 2 attributes in my class, knowing that they are Boost::multi_array and that their constructor takes as input a parameters that my class constructor takes also.

i.e : my PoreNetwork class' constructor takes 1 argument esize that is an int, that is also the argument of the constructor for its attributes Radiuses and States.

Félix Cantournet
  • 1,941
  • 13
  • 17

3 Answers3

2

The best way to initialise members is to use initialise list. But you still need to pay attention to the member declaration order and initialise orders.

class PoreNetwork
{
private: 
    int Size;  // note, put Size in front of States/Radiuses members
public:
    PoreNetwork(int esize);
    int getSize();
    StateNetworkType States;
    RadiusNetworkType Radiuses;
};

PoreNetwork::PoreNetwork(int esize)
: Size(esize),        // important to initialise Size first
  States(boost::extents[Size][Size][Size]),
  Radiuses(boost::extents[Size][Size][Size]) 
{
  cout << "esize = " << esize << endl;
}

If your do not initialise Size first, it's undefined behavior to initialise States and Radiuses and Size has not initialised with yet.

 PoreNetwork::PoreNetwork(int esize)
    : States(boost::extents[Size][Size][Size]),      // Undefined behavior as Size is not initialised yet
      Radiuses(boost::extents[Size][Size][Size]),
      Size(esize) 

If yo don't put Size in in front of States/Radiuses in the member list, you get compiler warning.

billz
  • 44,644
  • 9
  • 83
  • 100
0

use the initializer list:

PoreNetwork::PoreNetwork(int esize) :
  States(boost::extents[esize][esize][esize]),
  Radiuses(boost::extents[esize][esize][esize]),
  Size(esize) 
{
...
}
stijn
  • 34,664
  • 13
  • 111
  • 163
  • 1
    hmm, a problem, you should put Size(esize) on the top of initialise list, otherwise it's undefined behavior to initialise States and Radiuses – billz Nov 09 '12 at 07:55
  • ah good point, I meant to replace Size with esize there but forgot.. fixed; Size(esize) cannot be put on top because members should be initialized in the order declared, and in the class definition Size comes last – stijn Nov 09 '12 at 07:55
0

Member variables constructors are called like this:

PoreNetwork::PoreNetwork(int esize) :
  States(boost::extents[esize][esize][esize]),
  Radiuses(boost::extents[esize][esize][esize])
{
  ...
}

This means that it's hard to work with the constructor arguments inside the body before you apply them to your member variables. Using a function like boost::extents if often the only option if you can't call resize() (or something similar).

Macke
  • 24,812
  • 7
  • 82
  • 118