CObject
- абстрактный класс, потому что print()
- абстрактный. Таким образом, вы НЕ МОЖЕТЕ создавать экземпляры CObject
напрямую. Вы можете создавать только конкретные производные классы, которые реализуют print()
.
Вызов std::make_unique<CObject>(...)
пытается создать экземпляр CObject
, поэтому в вашем коде происходит сбой. Вместо этого вам нужно указать производный класс, например: std::make_unique<CButton>(...)
.
Однако показанный вами метод add()
не будет работать по ряду причин:
нет способа узнать, был ли переданный CObject
выделен в автоматической или динамической памяти. Пример main()
, который вы показали, создает объекты в автоматической памяти, но для удаления по умолчанию std::unique_ptr
(std::delete
) вместо этого требуется динамическая память.
вызывающий абонент не может указать правильный тип для передачи параметру шаблона T
std::make_unique()
.
ни один из ваших производных классов не имеет конструктора, который принимает CObject
в качестве входных данных, поэтому вы не можете указать переданный CObject
в параметре args
std::make_unique()
.
Вам нужно изменить add()
, чтобы вместо него взять std::unique_ptr<CObject>
, а затем вы можете просто std::move()
ввести его в vector
, например:
virtual void add(std::unique_ptr<CObject> src)
{
m_src.push_back(std::move(src));
}
Пусть вызывающая сторона обрабатывает создание нужного объекта, add()
просто становится владельцем этого объекта:
int main()
{
CWindow a("Sample window", CRect(10, 10, 600, 480));
a.add(std::make_unique<CButton>(1, CRect(0.1, 0.8, 0.3, 0.1), "Ok"));
a.add(std::make_unique<CButton>(2, CRect(0.6, 0.8, 0.3, 0.1), "Cancel"));
}
В противном случае, если вы хотите, чтобы add()
позвонил std::make_unique()
от имени вызывающего абонента, вам понадобится что-то более похожее на это:
template<class T, class... Args>
void add(Args&&... args)
{
m_src.push_back(std::make_unique<T>(args));
}
...
int main()
{
CWindow a("Sample window", CRect(10, 10, 600, 480));
a.add<CButton>(1, CRect(0.1, 0.8, 0.3, 0.1), "Ok");
a.add<CButton>(2, CRect(0.6, 0.8, 0.3, 0.1), "Cancel");
}