#c #boost #initialization #shared-ptr #member
#c #повышение #инициализация #общий-ptr #Участник
Вопрос:
У меня есть несколько классов, которые являются производными от чистой виртуальной базы:
class base {
public:
virtual int f() = 0;
};
class derived_0 : public base {
public:
int f() {return 0;}
};
class derived_1 : public base {
public:
int f() {return 1;}
};
Для краткости я ввел только два производных класса, но на практике у меня их больше.
И я хотел бы создать класс, который имеет постоянный общий указатель на базу. Я хотел бы выполнить следующее, но я не могу, поскольку я должен инициализировать указатель const в списке инициализации:
class C{
public:
C(bool type) {
if(type) {
derived_0* xx = new derived_0;
x = shared_ptr<base>( xx );
}
else {
derived_1* xx = new derived1;
x = shared_ptr<base>( xx );
}
}
private:
const share_ptr<base> x;
};
Как я могу получить эту функциональность?
Комментарии:
1. Вы забыли пометить
base::f()
какvirtual
2. Интересно, что именно представляют собой сообщения об ошибках.
Ответ №1:
Вы инкапсулируете создание объекта в функцию, например:
shared_ptr<base> create_base(bool type) {
if(type) {
return make_shared<derived_0>();
}
else {
return make_shared<derived_1>();
}
}
А затем вы можете использовать его в своем списке инициализации:
class C{
public:
C(bool type)
: x(create_base(type))
{}
private:
const share_ptr<base> x;
};
Ответ №2:
В простых случаях, подобных этому точному примеру:
class C
{
shared_ptr<Base> const x;
public:
C( bool type )
: x( type
? static_cast<Base*>( new Derived_0 )
: static_cast<Base*>( new Derived_1 ) )
{
}
};
(И да static_cast
, или, по крайней мере, один из них необходим.)
В более общих случаях, когда логика принятия решений более сложна, вы можете захотеть создать статическую функцию, которая возвращает shared_ptr
, например:
class C
{
shared_ptr<Base> const x;
static shared_ptr<Base> makeSharedPtr( bool type );
public:
C( bool type )
: x( makeSharedPtr( type ) )
{
}
};
Это позволит использовать любую мыслимую логику (а также более сложный набор
параметров).
Комментарии:
1. Обратите внимание, что в вашем первом случае с троичным оператором
static_cast
подобное использование означает, что деструктор должен быть виртуальным. Если вы вместо этого создадите временныйshared_ptr
указатель, сам указатель может сохранить точный производный класс для последующего удаления.2. @MarkB Но в целом, если класс полиморфный, вы хотите, чтобы деструктор был виртуальным.