1

I have a abstract class named Base from which I derived a class(Derived) as follows:

#include <iostream>
#include <string>
#include <memory>

class Base
{
public:
    virtual void printClass()const = 0;
    virtual ~Base(){}
};

class Derived: public Base
{
private:
    int m_var1;
    std::string m_var2;
public:
    Derived() = default;
    Derived(const int& v1, const std::string& v2)
        :m_var1(v1), m_var2(v2)
        {        }

    void printClass()const override
    {
        std::cout << "Derived Class with\t";
        std::cout << m_var1 << " " << m_var2 << std::endl;
    }
    ~Derived(){ std::cout << "Derived destroyed" << std::endl; }
};

Now in the main() to make use of polymorphisum I could declare as follows:

int main()
{
    std::shared_ptr<Base> Obj[3];
    Obj[0] = std::make_shared<Derived>(1,"One");
    Obj[1] = std::make_shared<Derived>(2,"Two");
    Obj[2] = std::make_shared<Derived>(3,"Three");

    for(const auto& it: Obj)
        it->printClass();
    return 0;
}

However, I am currently trying to learn more about the std::shared_ptr<>() and its custom deletion technics and I came across following statement.

std::shared_ptr<Base> Obj(new Derived[3], [](Derived* obj){ delete[] obj; });

and

std::shared_ptr<Base> Obj(new Derived[3] = { 
                                              {1,"One"}, 
                                              {2,"Two"}, 
                                              {3,"Three"} 
                                           }, 
                                           [](Derived* obj){ delete[] obj; });

My questions are:

  1. Why I can not initialize or pass values to the constructor of Derived class in following manner, even-though I have a costume defined constructor available for the derived class? or am I missing something?
  2. If so what would be the correct way of initializing and accessing such array of derived class elements?
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • What would you *do* with the resulting shared pointer? You couldn't access any but the first array element. – Kerrek SB Apr 08 '18 at 22:18
  • @KerrekSB: Yes, exactly that's what I experienced. I even tried to increment the pointer(like we do in normal array pointer case), but that did not work. Now the question is what happens exactly when I create an array like above? can I access those(i.e `Derived[1]` and `Derived[2]` ) ? – JeJo Apr 08 '18 at 22:28
  • 1
    There's nothing special about the array. The entire problem comes from casting the Derived pointer to a Base pointer, which effectively throws away all information about the ambient array. – Kerrek SB Apr 08 '18 at 22:35

1 Answers1

2

You can call the constructor like this:

std::shared_ptr<Base> Obj{
    new Derived[3]{ {1,"One"}, {2,"Two"}, {3,"Three"} },
    [](Derived* obj){ delete[] obj; }
};
Jodocus
  • 7,493
  • 1
  • 29
  • 45
  • Yes that works. So here we can not do like STL containers like for example: `std::map mp = { {1,"One"}, {2,"Two"}, {3,"Three"} };`. Could you also explain, why its like that? and also how can access each members in the array? – JeJo Apr 08 '18 at 14:20
  • 2
    You can, but not when creating a temporary. See the [syntax](http://en.cppreference.com/w/cpp/language/copy_initialization) for *copy-initialization*. – Jodocus Apr 08 '18 at 14:43