Puntero a objeto como argumento de un constructor
Frecuentes
Visto 3,002 veces
0
Bien, digamos que tengo una clase base abstracta aleatoria Base
y tengo una clase Foo
que contiene un puntero a esta clase base como miembro de datos. Entonces
class Foo
{
public:
Foo(Base*);
private:
Base* ptr;
}
Ahora, la razón por la que uso un puntero a la clase base es porque quiero poder elegir qué clase derivada mi Foo
objeto tiene un puntero a. Ahora, la parte complicada es, para mí, la implementación del constructor para Foo
.
Si lo hago asi
Foo::Foo(Base* _ptr)
{
Foo::ptr = _ptr;
};
sería posible para el usuario ajustar el objeto señalado por Foo::ptr
desde _ptr
seguirá existiendo después de que el constructor haya terminado. No puedo hacer que el objeto señalado por _ptr
constante porque Foo::ptr
necesita actualizarse regularmente. Ahora estaba pensando en agregar una línea _ptr = NULL
al final del constructor, pero eso también podría ser peligroso, ya que el usuario podría intentar desreferenciar _ptr
.
La única manera que se me ocurre para hacer este trabajo es hacer una copia del objeto señalado por _ptr
e inicializando Foo::ptr
a la dirección de esa copia. Pero entonces el objeto señalado por _ptr
necesitaría tener una función miembro Clone()
o algo similar porque no puedo llamar al constructor de copia para un objeto del cual no conozco la clase en tiempo de compilación.
Entonces, ¿hay alguna manera elegante de hacer esto si no hay Clone()
? ¿O es realmente la única posibilidad?
2 Respuestas
0
Construir a partir de un unique_ptr
. De esa manera, su usuario no tiene acceso al puntero después de que se haya utilizado en la creación de un Foo
objeto (a menos que realmente quiera y use get
).
p.ej
#include <memory>
struct Bar {};
struct Foo {
Foo(std::unique_ptr<Bar>&& ptr) : ptr_(std::move(ptr)) {}
std::unique_ptr<Bar> ptr_;
};
int main()
{
std::unique_ptr<Bar> tt(new Bar());
Foo f(std::move(tt));
return 0;
}
contestado el 03 de mayo de 12 a las 20:05
Así que esto todavía funcionaría con std::unique_ptr<DerivedFromBar> tt(new DerivedFromBar());
en la main()
¿función? Y el usuario necesitaría saber que tiene que usar un unique_ptr
? ¿O es posible un lanzamiento implícito de un puntero regular a un unique_ptr
? creo que no - Wouter
@Wouter unique_ptr<DerivedFromBar>
se convierte a unique_ptr<Bar>
. El punto de unique_ptr
aquí es que claramente estableces la propiedad en cada momento. El usuario lo construye, lo usa, y tan pronto como solía construir un Foo
renuncia a la propiedad mediante el uso move
en eso. - PMR
Oh sí, lo siento, quise decir std::unique_ptr<Bar> tt(new DerivedFromBar());
, pero yo veo. Entonces unique_ptr
actúa como un puntero regular (con propiedad explícita en todo momento), pero el elenco de regular a unique_ptr
Pregunté acerca de que probablemente no existe, ¿verdad? Dado que no hay forma de verificar si es el único puntero a ese objeto. - Wouter
@Wouter No necesariamente es necesario new
el puntero en el momento de unique_ptr
construcción, pero puede construir el unique_ptr
más tarde desde un puntero ya asignado. Aunque no hay una conversión implícita a un unique_ptr
. Eso sería muy peligroso. En esta solución, su cliente es activamente consciente de ceder el control. - PMR
Está bien, eso es lo que pensé. ¡Gracias! - Wouter
0
Una alternativa es usar punteros inteligentes. De esa forma, la propiedad se asigna a la implementación del puntero inteligente.
contestado el 03 de mayo de 12 a las 20:05
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ pointers constructor or haz tu propia pregunta.
Si usa C++ 11, podría resolver esto usando la semántica de movimiento. - Björn Pollex
Agregar "_ptr = NULL" no haría nada, ya que "_ptr" se pasa por valor al constructor. - fferen
¿Qué pasa con un
clone
¿método? - David Brown@DavidBrown No creo que haya nada malo en particular, pero significa que el usuario tendría que limpiar su propio desorden, es decir, tendría que eliminar
_ptr
ellos mismos. No sé por qué, pero realmente no me sienta bien. Tal vez me equivoque y elClone()
El método está bien, pero me gustaría saber las alternativas, no obstante. - Wouter