Search code examples
c++dynamicdynamic-memory-allocationobject-slicing

Creating an array in c++ of type superclass to store subclass objects dynamicaly


Please consider the following code :

    #include <iostream>
    using namespace std;
    class superclass;
    class subclass;
    class subclass2;
    class superclass
    {
    public:
        unsigned int a;
        superclass **superman;

    };
    class subclass : public superclass
    {
    public:
        unsigned int b;
    };
    class subclass2 : public superclass
    {
    public:
        unsigned int b;
    };
    class runner
    {
    public:
        superclass **superman;
        runner()
        {
            *superman=new superclass[2];
            superman[0]=new subclass;
            superman[0]->a=3;
            superman[1]=new subclass2;
            superman[1]->a=4;
        }

    };
    int main() {

        runner r;
        cout<<r.superman[0]->a<<" "<<r.superman[1]->a;
        return 0;
    }

As you can see I want to create a dynamicaly alocated storage of references to a parent class each of which can then point to a child class how ever I do not know how to extract the child class out again from that array so i may access its variable b;

I have tried the following approaches but they have not worked for me and give the error "conversion from 'superclass*' to non-scalar type 'subclass' requested" and "conversion from 'superclass*' to non-scalar type 'subclass2' requested"

    subclass s1=r.superman[0];
    subclass2 s2=r.superman[1];

I am sure I am missing something small.

PS: I could not find a similar question, but if it exists, please redirect me, also i would like a solution that does not require me to use vector or any inbuilt pre-existing library class.


Solution

  • You really want smart pointer in this case and superclass doesn't need to have a pointer to itself. You can can store superclass pointer in vector which points to real derived class so the polymorphism still works:

    #include <memory>
    #include <vector>
    
    struct superclass
    {
    public:
      superclass() : a(0) {}
      virtual ~superclass() {}  // it's important to define virtual destructor as superclass is a base class
      int getA() const { return a; }
    
    private:
      unsigned int a;
    };
    
    class subclass : public superclass
    {
    public:
        unsigned int b;
    };
    class subclass2 : public superclass
    {
    public:
        unsigned int b;
    };
    
    class runner
    {
    public:
      std::vector<std::unique_ptr<superclass>> superman;
      runner()
      {    
          superman.emplace_back(new subclass());
          superman.emplace_back(new subclass2());
      }    
    };
    

    Then you can access it simply:

       int main() 
       {    
           runner r;
           std::cout << r.superman[0]->getA() <<" " < <r.superman[1]->getA();
           return 0;
       }
    

    Side note: hide your data if you can, access data through set/get functions, don't declare members as public.