Search code examples
c++inheritanceabstract-classabstract-base-class

C++ "Pure virtual method called" with use of abstract baseclass


I am using a abstract baseclass with only pure virtual methods, to have a interface behavior (yes, I am coming from Java) in C++. As far as I did my research this seems to be the way to go.

I have to abstract base classes, GraphReader and Graph.

class Graph{
   public:
   Graph() {};
   virtual ~Graph() {};
   virtual void layout() = 0;
   virtual std::vector<std::shared_ptr<Node>> getNodes() = 0;
   virtual std::vector<std::shared_ptr<Edge>> getEdges() = 0;

   protected:

};

class GraphReader{
   public:
   GraphReader(std::string fileName_) :
         fileName(fileName_) {};
   virtual ~GraphReader() {};
   virtual Graph* read() = 0;

   protected:
   std::string fileName;
};

These both have derived classes that inherit from GraphReader/Graph.

class OgdfGraph : public Graph{
   public:
   OgdfGraph();
   virtual ~OgdfGraph();
   void setOgdfGraph(ogdf::Graph &oGraph);
   std::vector<std::shared_ptr<Node>> getNodes();
   std::vector<std::shared_ptr<Edge>> getEdges();
   void layout();

   private:
   [...]

};

class OgdfGmlReader : public GraphReader {  
   public:
   OgdfGmlReader(std::string fileName);
   virtual ~OgdfGmlReader();
   Graph* read();    
};

With the read() function returning the Graph* value as follows:

Graph* OgdfGmlReader::read() {

   [...]

   OgdfGraph og;
   og.setOgdfGraph(G);
   Graph* graph = &og;

   return graph;
}

In my main I do the following:

   OgdfGmlReader tr = OgdfGmlReader("../data/lesmiserables.gml");
   GraphReader* gr = &tr;
   Graph* graph = gr->read();

   graph->layout();

The loading of the graph works, but when I call the layout function on graph, I get the following error (on runtime, it compiles):

pure virtual method called
terminate called without an active exception
Aborted (core dumped)

Does this problem come from the fact that I return the Graph and I am not directly before it assigning the derived class to its parent class as with the GraphReader? I am the most confused as it works for the GraphReader but not for the Graph (returned from the GraphReader), as it is quite the same for my understanding.

Any help how to solve this issue (while possibly maintaining the inheritance architecture) is greatly appreciated!

Thank you very much in advance!


Solution

  • The problem is in Read function:

    The instance of OgdfGraph og is local variable which is assigned to graph is returned from Read function. Please note that the variable og will go out of scope and deleted once Read function has executed. Hence graph will remain just a pointer to Graph* without any valid instance allocated to it.

    You can fix it by changing OgdfGraph og as OgdfGraph* pog = new OgdfGraph()