Armazenar objetos heterogêneos no vetor com objetos alocados-stack
-
05-07-2019 - |
Pergunta
armazenar objetos no vetor heterogêneo com objetos alocados-stack
Olá,
dizer que tenho uma CA classe abstrata, derivado em CA1, CA2, e talvez outros.
Eu quero colocar objetos desses tipos derivados em um vetor, que eu embbed em uma CB classe. Para obter polimorfismo direito, eu preciso armazenar um vetor de ponteiros:
class CB
{
std::vector <CA*> v;
};
Agora, dizer que tenho a seguinte função principal:
int main()
{
CB b;
CA1 a1;
CA2 a2;
b.Store( a1 );
b.Store( a2 );
}
Como faço para escrever o void CB::Store(const CA&)
método de uma forma simples, de modo que os objetos armazenados sobreviver quando os objetos originais é destruído (o que não ocorre no exemplo simples acima).
O meu problema é que eu preciso primeiros objetos de cópia na pilha antes de copiar o seu endereço no vector, mas como eu posso criar um objeto de um tipo derivado? Claro, eu poderia usar RTTI, e procurar todos os tipos possíveis, criar e atribuir um ponteiro, e copiar (com carcaça adequada) o objeto no espaço alocado antes de empurrá-lo para o vector. Mas isso parece muito complicado, não?
Existe uma maneira mais simples?
(E sem usar a alocação dinâmica no! Principal)
Solução
Geralmente, você irá fornecer uma função de clone: ??
struct CA
{
virtual CA *clone(void) const = 0;
virtual ~CA() {} // And so on for base classes.
}
struct CA1 : public CA
{
virtual CA *clone(void) const
{
return new CA1(*this);
}
}
struct CA2 : public CA
{
virtual CA *clone(void) const
{
return new CA2(*this);
}
}
Isto é chamado um virtual construtor , você pode construto cópias de objetos em tempo de execução:
void CB::Store(const CA& pObject)
{
CA *cloned = pObject.clone();
}
Você deve considerar o uso do Boost.Pointer Container biblioteca . Seu código seria:
boost::ptr_vector<CA> objects;
void CB::Store(const CA& pObject)
{
objects.push_back(pObject->clone());
}
E agora você não tem nenhuma necessidade de gerenciar a memória sozinho. A biblioteca também respeita funções clone, e vai chamá-lo ao fazer cópias de seus objetos. Tutorial aqui .
Outras dicas
Parece que você precisa de uma função clone () em sua classe abstrata que suas classes derivadas irá implementar.
class CA
{
public:
virtual ~CA() {}
virtual CA* clone() const = 0;
}
class CA1 : public CA
{
public:
virtual CA *clone() const
{
return new CA1(*this);
}
};
Uma possibilidade seria templatize loja do tipo de seu argumento:
class CB
{
public:
template<class T>
void Store(const T& t)
{
v.push_back(new T(t));
}
private:
std::vector <CA*> v;
};
Um aviso: Ao contrário do "clone ()" solução publicado por outros, este é propenso a cortar. Por exemplo, esta multa funciona:
CB b;
CA1 a1;
CA2 a2;
b.Store(a1);
b.Store(a2);
Mas isso não:
CA1 a1;
CA* a = &a1;
b.Store(*a); //Ouch! this creates a new CA, not a CA1
Dar um ctor cópia protegida para CA impede tal utilização abusiva. No entanto, se ainda CA1 subclasse, a questão volta.