I have a polymorphic base class storing a std::vector<std::unique_ptr<Base>>
. I would like to initialize this vector in the derived classes. The sizes of these vectors are known at compile time and do not change after construction. In my current solution I have a pure virtual function initialize()
which is overriden in each Derived:
class Base {
public:
virtual void Initialize() = 0;
virtual ~Base() = default;
protected:
Base(std::size_t count) : m_data(count) {}
std::vector<std::unique_ptr<Base>> m_data;
};
class Derived1 : public Base {
public:
Derived1() : Base{ 8 } {}
void initialize() override {
m_data[0] = std::make_unique<Derived1>();
// ...
m_data[7] = std::make_unique<Derived1>();
};
};
class Derived2 : public Base {
public:
Derived2() : Base{ 24 } {}
void initialize() override {
m_data[0] = std::make_unique<Derived2>();
// ...
m_data[23] = std::make_unique<Derived2>();
};
};
However, I am not pleased with this solution; Partly because of the use of a virtual function and the redundancy ofm_data[0] = ...; ... m_data[N-1] = ...
m_data[0] = ...; ... m_data[N-1] = ...
.
I would like to assign m_data
like this:
m_data = {
std::make_unique<Derived1>(),
// ...
std::make_unique<Derived1>()
}
which does not work because of std::unique_ptr
s deleted copy ctor.
Here is a more realistic sample of my code
What is the best way to initialize the vector in the derived classes? I am using C++17.
However, I am not pleased with this solution; Partly because of the use of a virtual function
If the virtual function is a problem, then make it non-virtual.
and the redundancy
You can simply use a loop to get rid of the repeated assignments:
for (auto& ptr : m_data)
ptr = std::make_unique<Derived1>();
To avoid redundancy from having identical code for each type, there is tool for that in C++, templates:
template<class D, std::size_t N>
struct BaseT : Base {
BaseT() : Base{N} {}
void Initialize() override {
for (auto& ptr : m_data)
ptr = std::make_unique<D>();
};
};
struct Derived1 : BaseT<Derived1, 8> {};
struct Derived2 : BaseT<Derived2, 24> {};
In this case, the template argument is the derived type. There is a name for such idiom: Curiously Recurring Template Pattern.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.