C. Downer
C. Downer

Reputation: 205

Accessing subclass methods in array of pointers

I've been having trouble accessing the "getDegreeProgram()" method in my objects that are set to my array of pointers; all of my baseclass methods are working, but for some reason, my subclass methods aren't even visible. I'm suspecting that I don't have the syntax right, and its converting all of my subclass objects to the baseclass of student.

roster.h:

   class roster { 
   private:   
   student** classRosterArray; //array of pointers

roster.cpp function that creates my objects and sets them to the array of pointers


   void roster::createStudentObject() {
      classRosterArray = new student *[5]; //array of pointers
   if (degreeProgramInput == "NETWORK") {
      classRosterArray[rosterCounter] = new networkStudent();
   }
   else if (degreeProgramInput == "SECURITY") {
      classRosterArray[rosterCounter] = new securityStudent();
   }
   else classRosterArray[rosterCounter] = new softwareStudent();  
   }

student.h subclasses in question (they're subclasses of my baseclass "student")

    class networkStudent:public student {
    private: 
      int networkDegree;
    public:
      int getDegreeProgram();
      networkStudent();
    };
    class securityStudent:public student {
    private:
      int securityDegree;
    public:
      int getDegreeProgram();
      securityStudent();
    };
    class softwareStudent:public student {
    private:
      int softwareDegree;
    public:
      int getDegreeProgram();
      softwareStudent();
    };    

Upvotes: 0

Views: 510

Answers (2)

Raghu
Raghu

Reputation: 43

There are two you ways you can go about it.

  1. Runtime Polymorphism - This method will require less code refactoring but at the cost of runtime. Each instance of a polymorphic class will have a pointer(vptr) to a table(vtable) of pointers to the different versions of the virtual function. This table will be used for finding the right version of the virtual function at runtime.

You can achieve runtime polymorphism here by making the getDegreeProgram function virtual in base class ie., Student and override it in derived classes ie., securityStudent, networkStudent and softwareStudent.

class Student {
...
public:
  virtual int getDegreeProgram() = 0; // notice the virtual keyword and 0 at the end. 
                                      // 0 is for saying that it is pure virtual, meaning
                                      // we don't have any definition for this function in
                                      // this class. Such a class is also called as 
                                      // abstract class
...
}

class securityStudent : Student {
...
public:
 int getDegreeProgram() override 
 {
     // do the stuff you want to do
 }
...
}

//  driver stub
...
 Student *student;
 securityStudent sStudent;
 networkStudent nStudent;
 .
 .
 student = &sStudent;
 student->getDegreeProgram(); // calls security student implementation of getDegreeProgram
 student = &nStudent;
 student->getDegreeProgram(); // calls network student implementation of getDegreeProgram
...
  1. Static Polymorphism or CRTP or Simulated Dynamic Binding - This method does the same thing as above but with the advantage of knowing the type at compile time by means of some casting magic (below). Even this approach has its limitation like kludgy syntax and some amount of refactoring which is a lot more than in the 1st case and lack of readability due to terseness of templates etc.

The trick here is to get the derived class' information at compile time and typecast the this pointer of the base class to that of the derived class. :-)

template <typename StudentType>
class Student {
...
public:
  int getDegreeProgram() 
  {
     return (static_cast<StudentType*>(this))->getDegreeProgramImpl();
  }
...
}

class securityStudent : public Student<securityStudent> {
...
public:
  int getDegreeProgramImpl()
  {
    // write your specifc implementation here
  }
...
}

// driver stub
...
 securityStudent sStudent;
 networkStudent nStudent;
 .
 .
 sStudent.getDegreeProgram(); // calls security student implementation of getDegreeProgram
 nStudent.getDegreeProgram(); // calls network student implementation of getDegreeProgram
...

Upvotes: 0

Kunal Puri
Kunal Puri

Reputation: 3427

As far as I understood, you are trying to access the elements of classRosterArray and trying to call getDegreeProgram().

For this problem, Make the getDegreeProgram() virtual function.

student.h

class student {
...

public:
    virtual int getDegreeProgram() = 0; // pure virtual function
};

Subclasses of student

class networkStudent:public student {
private: 
  int networkDegree;
public:
  virtual int getDegreeProgram();
  networkStudent();
};
class securityStudent:public student {
private:
  int securityDegree;
public:
  virtual int getDegreeProgram();
  securityStudent();
};
class softwareStudent:public student {
private:
  int softwareDegree;
public:
  virtual int getDegreeProgram();
  softwareStudent();
};

Suggestion:

In this case, Because getDegreeProgram() seems to be a getter function, I think you should declare it as a const function.

Edit:

As rightly said by Richard, In C++ 11, override keyword was introduced for this purpose for the sub classes. So, instead of writing virtual int getDegreeProgram();, you could write int getDegreeProgram() override; also.

Upvotes: 1

Related Questions