c++ - Implementing Data Structure using levels of abstraction -


lets assume i'm implement stack using dynamic array allocation. have following classes , functions.

data.h

class data { public:    data(std::string fname, int age) : name(fname) , age(age) {}  private:    std::string name;    int age; } 

stackarray.h

#include "data.h"  class stackarray { public:     stackarray(int ssize) : size(ssize), top(-1)     {        dataarray = new data[size];     };      ~stackarray() { delete[] dataarray; };      stackarray& operator=(stackarray& stackarrayobj) { //use copy&swap here };     stack(const stackarray& stackarrayobj);     bool isfull();     bool isempty();     void push(data& dataobj);     void pop();  private:     data* dataarray;     int top;     int size; } 

if implement above, works quite well. of recent, i've been asked implement above 2 is, have separate implementation core stack functionalities.

so now, if move push, pop, isfull, isempty new stack definition, purpose of class stackarray implemtation?.

the 2 solution have tried follows:

new class implemtation

class stackadt {  public:     stackadt();     virtual ~stackadt() = 0;     virtual bool isfull() = 0;     virtual bool isempty() = 0;     virtual void push(data& dataobj) = 0;     virtual void pop() = 0; } 

then, extending class stackarray class, thereby forcing implement pure virtual function.

the second, not elegant(my opinion) way have done that:

i have complete definition , implementation of stack in stackadt, , calling corresponding methods in equivalent methods in stackarray. this:

stackadt - push

bool stackadt::push(const data& dataobj) {     if(!isfull)        return false;     else     {        top++;        dataarray[top] = dataobj;     }     return true; } 

then inside stackarray - push, i'll this:

bool stackarray::push(const data& dataobj) {     stackadt dopush;     dopush.push(dataobj); } 

not sure both methods of combining 3 classes - data, container , stack - suppose be.

how can solve design problem? or @ least align "best practice" if there's such.

when talking abstractions, should try identify core aspects of trying implement. normally, aspects can represented interface.

since in c++, unlike other languages java, not have specific interface declaration syntax, can use pure virtual classes.

generically speaking, stack data structure following lifo access structure , nothing more.

even though being limited amount of memory, don't see reason why basic stack should have size limit @ first. more abstracted way of thinking size limit verify whether stack accepts more elements or can provide , element through pop invocation.

so, might think stack basic interface follows:

class stack { public:     virtual ~stack()=0;     virtual data& pop() throw (std::out_of_range) = 0;     virtual void push(data&) throw (std::out_of_range) = 0;     virtual bool ispoppable() = 0;     virtual bool ispushable() = 0; } 

then can start thinking implementations. simple implementation doing array:

class stackarray : public stack { private:     data* marray;     int msize;     int mpointer;     stackarray(int size) : msize(size), mpointer(0) {         marray = new data[msize];     }     virtual ~stackarray() {         delete [] marray;     } public:     void push(data& el) throw (std::out_of_range) {         if (!ispushable()) throw std::out_of_range("cannot push stack");         marray[mpointer++] = el;     }      data& pop() throw (std::out_of_range) {         if (!ispopable()) throw std::out_of_range("cannot pop stack");         return marray[mpointer--];     }      bool ispushable() {         return mpointer < msize;     }      bool ispoppable() {         return mpointer > 0;     } } 

going further, think of linked-list-based stack:

class datanode { private:     datanode* next;     data* data; public: // trivial impl. ommited     bool hasnext();     datanode* getnext();     data* getdata();     void setnext(datanode* next);     void setdata(data* data); }  class stacklinkedlist : public stack { private:     datanode* root; public:     stacklinkedlist():pointer(0) {}     virtual ~stacklinkedlist() {}     void push(data& el) throw (std::out_of_range) {         if (!ispushable()) throw std::out_of_range("cannot push stack");         datanode* n = new datanode();         n->setdata(&el);          datanode* pointer = root;         if (root == null) {             pointer = n;         } else {             while (pointer->hasnext()) {                 pointer = pointer->getnext();             }              pointer->setnext(n);         }     }      data& pop() throw (std::out_of_range) {         if (!ispoppable()) throw std::out_of_range("cannot pop stack");         datanode* pointer = root, previous = null;         while (pointer->hasnext()) {             previous = pointer;             pointer = pointer->getnext();         }          data* ret = pointer->getdata();         delete pointer;         if (previous != null) {             previous->setnext(null);         }          return *ret;     }      bool ispushable() {         return true;     }      bool ispoppable() {        return root != null;     } } 

Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -