0

in my C++ class at university, i have to implement a Directed, weighted graph. As internal representation i have to implement a two-dimensional array, which stores the information about the edges between the vertices in the graph.

okay, i´ve implemented a C++ class "TwoDimArray" with an overloaded [] operator.

it works well as long as i instantiate objects of TwoDimArray in main(). But it does not as class member.

My Class for representation of the graph is "DirectedGraph" and has a private member "adjacencyMatrix" of Type TwoDimArray*.

In the constructor of my DirectedGraph class i intend to fill the array with zeros initially, indicating "there is no edge between the nodes i and j".

okay, and this is where it all goes wrong. I can write till coordinate [0][2] (when initializing the graph with 3 nodes, so the array should have 3x3 cells). when trying to write at adress [1][0] the assignment operation crashes with segmentation fault. So the assignment operations succeed n times and fail beginning at n+1 (where n is the number of vertices).

Any ideas what i am doing wrong?

My TwoDimArray Class (first header, then implementation):

#ifndef TWODIMARRAY_H_INCLUDED
#define TWODIMARRAY_H_INCLUDED


class TwoDimArray{


 private:


   int* pArr;
   int rows;
   int cols;


 public:

   TwoDimArray(int rows, int cols);
   int* operator[](int row);
   ~TwoDimArray();

};


#endif // TWODIMARRAY_H_INCLUDED

The implementation:

#include <TwoDimArray.h>

TwoDimArray::TwoDimArray(int nrOfRows, int nrOfCols){

   rows = nrOfRows;
   cols = nrOfCols;

   //allocate memory
   pArr = new int[rows * cols];


 }


int* TwoDimArray::operator [](int row){

   return &pArr[row * cols];
}


  TwoDimArray::~TwoDimArray(){

   delete[] pArr;
}

Directed Graph header:

    #define DIRECTEDGRAPH_H_INCLUDED
    #include <string>
    #include <list>
    #include <Vertex.h>
    #include <TwoDimArray.h>


    using namespace std;

    /**
     * DOCUMENTATION
     * ======================
     * object oriented Implementation
     * of the abstract
     * Datatype Directed Graph
     * as C++ class
    */

    class DirectedGraph{


       private:

          int maxVertices;
          list<Vertex> vertices;
          TwoDimArray* adjacencyMatrix;
          bool edgeExists(string srcName, string tgtName);
          int vertexExists(string vName);



       public:

          //DirectedGraph();
          DirectedGraph(int maxVertices);
          ~DirectedGraph();


          void AddVertex(Vertex& v);
          void AddEdge(Vertex& source, Vertex& target, int weight);

          int getMaxVertices() const;
          list<Vertex> getVertexNames()const;

          void PrintGraph();

    };




    #endif // DIRECTEDGRAPH_H_INCLUDED

Directed Graph Implementation (only the constructor):

    DirectedGraph::DirectedGraph(int maxV){

       this->maxVertices = maxV;

       //initialize the array
       this->adjacencyMatrix = new TwoDimArray(maxV, maxV);

       int i = 0;
       int j = 0;

       for(i = 0; i <= maxVertices - 1; i++){

          for(j = 0; j <= maxVertices - 1; j++){

             // ==> the fatal assignment
             //fails at i = 1 and j = 0

             *adjacencyMatrix[i][j]=0;
             cout << "assigned " << i << " " << j << "with 0"<<endl;
          }
       }
    }

any suggestions? i guess its not okay to declare the class member as TwoDimArray* instead of TwoDimArray, but otherwise it does not compile.

What i´ve also tried is:

    DirectedGraph::DirectedGraph(int maxV){

       this->maxVertices = maxV;
               //try to instantiate TwoDimArray 
       TwoDimArray myArr(maxV, maxV);
       this->adjacencyMatrix = myArr;

       int i = 0;
       int j = 0;

       for(i = 0; i <= maxVertices - 1; i++){

          for(j = 0; j <= maxVertices - 1; j++){

             // ==> the fatal assignment
             //fails at i = 1 and j = 0
             myArr[i][j]=0;
             cout << "assigned " << i << " " << j << "with 0"<<endl;
          }
       }
    }

but it fails at the same point. i am not very familiar with pointer logic in c++ i must admit...

any suggestions?

thanks in advance Roland

Monty Burns
  • 101
  • 1
  • 3
  • 10

2 Answers2

3

You have violated the Rule of Three. The easiest way to solve that is to avoid directly allocating memory:

class TwoDimArray{
 private:
   std::vector<int> arr;
   int rows;
   int cols;
 public:
   TwoDimArray(int rows, int cols) : arr(rows * cols);
   int* operator[](int row) { return &arr[cols*row]; }
};
Community
  • 1
  • 1
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
2

One problem is that you're not providing a copy constructor and assignment operator for TwoDimArray.

This breaks the following:

   TwoDimArray myArr(maxV, maxV);
   this->adjacencyMatrix = myArr;

and possibly other code.

See What is The Rule of Three?

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • ok i see why this->adjacencyMatrix = myArr does not work. I did not implement a copy constructor. but why does *adjacencyMatrix[i][j]=0; not work beginning with n+1?, i mean within main() myArray[i][j] = 0; works fine... – Monty Burns Jan 07 '13 at 19:46