Hi,

I am still rather green when it comes to C++ so be gentle with me. I am trying to create a dynamic array of objects (class Structure), each object represents a geometric (physical) structure. But for the sake of simplicity let's consider only one such object. Within each instance of Structure there are a number of planes, let's say i, each plane i has a variable number of points, j. Each point consists of three floats representing (x,y,z) coordinate triplets. This is standardised format of the data I have to read in.
I have created a simple second class, Point, which is supposed to contain one coordinate (x,y,z)triplet representing [i,j]. I therefore need to create a dynamic array of Point objects of size i,j(i) within the Structure object. I hope this is clear.

Clearly I am making some fundamental since the code will not compile.

I would appreciate some assistance with this.

Thanks


// Define Point class to assign (x,y,z) values 
// Create a 2D array of Point objects for each Structure
// i.e. Point[i][j] where
// i = number of planes in Structure (numPlanes)
// j = number of points in plane_i of Structure  (numPoints(i))
// Last modified 23.03.09
#include<iostream>
#include<ctype.h>
#include<math.h>
using namespace std;
 
class Point{
      public:
             float x,y,z;
// Point methods to set 
void SetX (float x) {x=x;}
void SetY (float y) {y=y;}
void SetZ (float z) {z=z;}
// constructor and destructor
Point(){
               x=y=z=0.0;
               };
                
Point::~Point();// destructor
 
};
 
// class Structure into which points are read in
 
class Structure{
      public:
             int referenceNumber,numPlanes,numP;
             int *numPoints;
//            int numPoints[];
             char referenceName[30], fileName[80];
             Structure();    // parameterless constructor
 //            Structure(char fileName);
             ~Structure();   // destructor
};
             
Structure::Structure(){
// Initialise everything to zero
int i,j,k; // i is number of planes in (structure)
           // j is number of points contained in (plane)_i - this is variable within
           // (structure) => consider use of vector 
           // k is index to step through coordinates of point i.e. x(k=0),y(k=1),z(k=2)
 
referenceNumber=numPlanes=numP=0;
 
           
// Get reference number of structure_i - not needed for this simple test
referenceNumber = 0;
// Get reference name of structure_i - not needed for this simple test
 
// Get number of planes (j) contained in structure_i 
cout << "Enter number of planes : \n";
cin >> numPlanes;
 
int *numPoints = new int[numPlanes]; // declare dynamic integer array for points[j] in each plane[i]
Point **pPoint = new Point*[numPlanes]; // declare dynamic **pPoints object array[i]
 
for (i=0;i<numPlanes;i++) { 
//Initialise numPoints[i] and pPoint[i] to zero
    numPoints[i]=0;
//    pPoint[i]=0;
}
// Get number of points (j) contained in plane i of structure
for (i=0;i<numPlanes;i++){
    cout << "Enter number of points in plane " << i+1 << " : \n";
    cin >> numPoints[i];
    }
    
    
//Allocate memory for 2D array of Point objects
for (i=0;i<numPlanes;i++) pPoint[i]=NULL;
 
for (i=0;i<numPlanes;i++){
    numP =numPoints[i];
    pPoint[i] = new Point [numP];
              if (pPoint[i]==NULL){
              cout << "\nNot enough memory for points.\n";
              // throw error exception class
              }
                     
   
                     //Now set the values of points to zero
                     for (j=0;j<numP;j++){
                     // call default constructor to set x,y,z to zero    
                     Point();
                     }
                             
   }
}
                  
 
 
Structure::~Structure(){
int j;
cout << "\nFreeing up memory...\n";
 
 for (j=0;j<numPoints;j++) delete [] pPoint[j]; 
 
 // then the rows...
 
 delete [] pPoint;// calls pPoint destructor and releases memory (avoid memory "leak")
    
    if (numPoints !=NULL){
              delete [] numPoints;
              numPoints=NULL;
              }
cout << "Done!\n";
}
 
 
int main(){
 
    return 0;
}

Ok: Not perfect but a good attempt:

First off scoping rules:

if you have a class variable e.g.

class A {
    int index;
};

Then that variable is effectively hidden by this

class A
{
   int Index;
   void run(int Index) const { Index+=20; } 
};

Note that run does not change Index in the class but a local value.

Hence

void SetX (float x) {x=x;}

is wrong. You could have (a) seen this by writing the function using const. e.g.

void SetX(const float Xvalue) { x=Xvalue; }

Had you done x=x; then the compile would have complained.

B) you don't qualify classes within a definition. e.g
for your destructor Point::~Point() is wrong since it is withn the definition.

C) Scope again!!! pPoint is declared in constructor. it is not a member of the class. So it goes out of scope at the end of the
Structure constructor. Lost memory. Additionally you cant delete it later

Finally: You are getting boged down in new/delete etc. Please, use OO first. That means you write a Plane class. That takes one plane.
A plane can then have a number of points (if it is a limited range)
or three if it is infinite. (or a normal + distance if you like).

That way you will find that you enrich your point class to have dot product etc. and Planes can be stored in a simple flat array or vector.

I can see what you trying to do !

But common show some courage !
get the first error and try to correct it ! read the error message !

Ok. Here is my second attempt (containing Point, Plane and Structure objects) no errors when compiling or linking under Dev-C++ v4.9.9.2. However I get an error message when attempting to execute under windows (see attachment)

Each Structure object should create an array of Plane objects which in turn create an array of Point objects. Is this the best way to do this? If not can someone please suggest a better method?

I need to clean up memory afterwards: is it best to do this with the destructor i.e.

Structure::~Structure(){... delete pPlane}

and then

Plane::~Plane(){... delete pPoint}

or as a block at the end.

/* Simple program to create a dynamic array of Structure objects (numStructure),i,
   where each structure object comprises (numPlane(i)) planes ,j, and 
   the jth plane comprises a plurality of points numPoint(j). 
   Thus we have a number of "ring"-like contours defined by the points in each plane
   
   For testing purposes this values all values input by user.
   
   In final program values will be read in from file
   
   Typically: numStructure                          ~20-30
              numPlane per Structure                ~20-50
              numPoints per Plane per Structure     ~200-500
   
   i.e. around 750,000 points (30*50*500)
   Of those 30 structures read in a maximum of 10 are of interest
   After points have been read in from file then need to determine
   i) nearest neighbours in plane and in adjacent planes (above and below)
   ii) midpoint of contour (plane)
   iii) calculate radius at each point etc. etc.
*/
 

#include<iostream>
using namespace std;
 

class Point{
      public:
             float x,y,z;
      Point();
      Point (float x, float y, float z);
      ~Point();
};
 
// define constructors for Point class    
Point::Point():x(0),y(0),z(0){
        }
Point::Point(float x, float y, float z):x(x),y(x),z(z){
                   }
Point::~Point(){}
 
class Plane{
      public:
             int numPoints;
      Plane();
      Plane(int numPoints);
//      ~Plane();
      void getPoints(int numPoints);
};
 
// define constructor and getPoints method for Plane class
Plane::Plane(){
               int numPoints=0;
               }
 
// getPoints method reads in number of points per plane (numPoints)
// and creates prompts user to input x,y,z triplet values,
// which are read into Point class object               
void Plane::getPoints(int numPoints){
        int j,k;
        float x,y,z;
        
// declare dynamic array of Point objects using pPoint
Point *pPoint = new Point [numPoints];
 
for (k=0;k<numPoints;++k){
    cout << "\nEnter values for x,y,z triplet " << k+1 << " : \n";
    cin >> x;
    cin >> y;
    cin >> z;
  
    pPoint[k].x=x;
    pPoint[k].y=y;
    pPoint[k].z=z;
   
}
// check that this works properly by writing values to screen
cout << "\nx \ty \tz\n";
for (k=0;k<numPoints;++k){
    cout << pPoint[k].x << "\t" << pPoint[k].y << "\t" << pPoint[k].z <<"\n";
}
cout << endl;
}     
 
class Structure{
      public: 
              int numPlanes;
      Structure();
      Structure(int numPl);
      ~Structure();
      
      void getPlanes(int numPlanes);
};
// declare constructor and getPlanes method for Structure class
// getPlanes reads in number of planes per structure and calls
// getPoints method (Plane class)
 
Structure::Structure(){
                       int numPlanes=0;
}
Structure::Structure(int numPlanes){
                         numPlanes=numPlanes;
                         }
 
void Structure::getPlanes(int numPlanes){
     int j;// indices for planes and points
     int *numP=NULL;
     Plane *pPlane = new Plane [numPlanes];
 
     numP = new int[numPlanes];
 
for (j=0;j<numPlanes;++j){
    numP[j]=0;
    cout << "\nEnter number of triplets for plane " << j+1 << " : ";
    cin >> numP[j];
    pPlane[j].getPoints(numP[j]);
    }
}
 

int main(){
int i,j,k,numPoints,numPlanes,numStructure;
float x,y,z;
int *numP,*numPl;
 
*numP=*numPl=0;
 
// For testing purposes number of structures,planes per structure and points per plane are
// input by the user. In the final program this will be read in from file.
 
cout << "\nEnter number of structures : ";
cin >> numStructure; // how many structures are to be read in
 
//try{
    Structure *pStructure = new Structure[numStructure]; // dynamic array of Structure objects
    numPl= new int[numStructure];
//}
//catch(EX_NotFound){
//                   goto freeMain;
//}
 

for (i=0;i< numStructure; ++i){
//    pStructure[k]=NULL;
    numPl[i]=0;
    
cout << "\nEnter number of planes : ";
cin >> numPl[i];
 
pStructure[i].getPlanes(numPl[i]);
}
 
cout << "Done!\n";
system("PAUSE");// prevent window disappearing
//goto freeMain;
 
//freeMain:
//         cout << "nCleaning up allocated memory\n";
//        if (pStructure !=NULL){
//                      delete pStructure;
//                        pStructure=NULL;
//         }
         
/*         if (pPlane !=NULL){
                    delete pPlane;
                    pPlane=NULL;
         }
         
         if (pPoint!=NULL){
         delete pPoint;
         pPoint=NULL;
         }
 */        
return 0;
 
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.