2

I'm trying to create an array of pointers using polymorphism. I will have the array of the superclass point to multiple subclasses. Is there anyway of doing this and still using a method from the subclass? Here's a sample code:

#include <iostream>


class Test1
{
public:
    Test1()
        : x(1)
    {}
    int get_x()
    {
        return x;
    }
private:
    int x;
};

class Test2 : public Test1
{
public:
    Test2()
        : y(2)
    {}
    void print()
    {
        std::cout << get_x() << ' ' << y << std::endl;
    }
private:
    int y;
};

class Test3 : public Test1
{
public:
    Test3()
        : y(3)
    {}
    void print()
    {
        std::cout << get_x() << ' ' << y << std::endl;
    }
private:
    int y;
};

int main()
{
    Test1** test = new Test1*[2];
    for (int i = 0; i < 2; i++)
    {
        if (i % 2 == 0)
        {
            test[i] = NULL;
            test[i] = new Test2;
        }
        else
        {
            test[i] = NULL;
            test[i] = new Test3;
        }
    }

    test[0]->print(); // ERROR. Is this even possible?
    test[1]->print(); // ERROR. Is this even possible?


    return 0;
}

Thank you I've only been coding for about 8 months.

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
aglasscage
  • 25
  • 3

2 Answers2

2

test[0]->print(); // ERROR. Is this even possible?

In general, yes. However, not with your code.

  1. If Test1 is going to be your base class and you're going to use new then it must have a virtual destructor (e.g., virtual ~Test1() {})
    • This is necessary for delete to work correctly when deleting a derived type via a pointer to the base class
  2. Any function you want to call using a pointer to the base class must exist on the base class (i.e., you need a print function in Test1)
  3. If you want the derived classes to have their own implementation of print then it must be declared virtual in the base class (e.g., virtual void print();)
    • If it dosn't make sense for Test1 to have an implementation of the print function then it can declare it pure virtual and not provide an implementation (e.g., virtual void print() = 0;) thus making it an abstract class
James Adkison
  • 9,412
  • 2
  • 29
  • 43
  • Can you be more specific on the virtual descructor? is my code in the superclass just virtual ~Test1(){} and in the sub classes I create destructors as well? – aglasscage Apr 18 '15 at 04:02
  • See [When to use virtual destructors?](http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors). – James Adkison Apr 18 '15 at 04:04
  • Ok so I guess I don't totally understand this. Will a virtual descructor work in my case? Because won't a virtual descructor make the class virtual and therefor I could never do this: Test1** test = new Test1*[2];. (I read the link you provided by don't really understand how it's supposed to work) – aglasscage Apr 19 '15 at 03:51
  • @aglasscage **No**, you will still be able to instantiate `Test1` with a virtual destructor and **you must have one** because you need to call `delete` on the base pointer (which is for derived types). You cannot instantiate an _abstract_ class (i.e., you wouldn't want to do #3). – James Adkison Apr 19 '15 at 17:11
  • I added the destructor and got it working. Thanks a lot man I appreciate all of the help. – aglasscage Apr 20 '15 at 06:14
1

It would be if Test1 had such a member function named print. Your code doesn't compile as-is because Test::print doesn't exist. So at the very least, you will have to define that member function. For it to be truly polymorphic, as the intent of the question suggests, you should make Test::print a virtual member function so that Test2's and Test3's implementations of that function would get called instead:

class Test1 { 
    ...
    virtual void print() {
        std::cout << "Test1" << std::endl;
    }
    ...
};

For more information, see this tutorial on virtual functions.

Barry
  • 286,269
  • 29
  • 621
  • 977