Search code examples
c++ooppointerspolymorphism

What's the advantage of binding a base class to a derived class as opposed to simply creating a derived class pointer?


Notice in this example I created a derived class pointer (Laser* pLaser = new Laser) instead of a base class pointer like (Boat* pLaser = new Laser). Is there an advantage creating a base class pointer instead? Thanks!

   #include <iostream>
    using namespace std;

    class Boat      
    {
        protected:
         int length;

        public:
         int getLength() { return length; }
         virtual void Model() = 0;
    };

    class Sailboat : public Boat        
    {
        protected:
         int mast;

        public:
         int getMast() { return mast; }
         virtual void Boom() = 0;
    };

    class Laser : public Sailboat       
    {
        public:
         Laser() { mast = 19; length = 35; }    
         ~Laser();                              

         void Model() { cout << "Laser Classic" << endl; }  
         void Boom() { cout << "Boom: 14 ft" << endl; }
    };


    int main()
    {
        Laser* pLaser = new Laser;      

        pLaser -> Model();
        cout << "Length: " << pLaser -> getLength() << "ft" << endl;
        cout << "Height: " << pLaser -> getMast() << "ft" << endl;
        pLaser -> Boom();

        return 0;
    }

Solution

  • Each one have a different purpose.

    Child pointer

    Laser* pLaser = new Laser purpose is to simply use dynamic allocation for this type, sometimes for sharing this data with other threads/processes. Usually you don't have to use it in C++, and you usually allocate this type on the stack.

    Parent pointer

    Boat* pLaser = new Laser This is a different story of polymorphism. If you want to store different type that implement the same interface you have to use this form (usually with smart pointers, but still same idea). For example, assume you want a container (e.g. std::vector) to include both Sailboat and Laser. Using this form you can do something like:

    std::vector<Boat*> vec = {new Laser(), new Sailboat()};
    for (auto &e : vec) {
        std::cout << e->getLength() << std::endl; 
    }
    

    As I mentioned, sometimes you have to use this form, and those times are when you have at lease one pure virtual function in you base class. In this case, you can't create an object on the stack of the base class (due to incomplete type). For exmaple:

    class Base {
    public:
        virtual int compare(int, int) = 0;
    };
    
    class Derived : public Base {
    public:
        int compare(int a, int b) {
            return a - b;
        }
    };
    
    int main() {
        //Base b; // Compilation error
        Derived c; // OK
        std::shared_ptr<Base> base_pointer = std::make_shared<Derived>(); // OK
        return EXIT_SUCCESS;
    }
    


    Read more about:

    Polymorphism C++