Llamar a funciones virtuales desde una referencia

Tengo una estructura como esta

struct structure
{
    BaseObject &A; //BaseObject has a function declared as virtual
};

En tiempo de ejecución, asigno dinámicamente un objeto a &A

structure *s = new structure;
DerivedObjectB *B = new DerivedObjectB(); //Derived class overloads the virtual function 
s->A = *B; //s is a pointer of the structure. S has been initialized 

Puedo compilar este código, pero recibo un error de falla de segmentación en tiempo de ejecución. Tengo una restricción de que no puedo usar un puntero. Esto no es una tarea. El compilador que estoy usando como compilador inverso tiene una restricción de usar punteros debido a un problema en la construcción de SSA

preguntado el 12 de junio de 12 a las 18:06

Ese código no se puede compilar, las referencias no son asignables. Muéstranos el código real. -

@ K-ballo No estoy de acuerdo (sobre la parte de compilación). -

"Tengo una restricción de que no puedo usar un puntero."¿Quién te daría una restricción tan tonta? ¿Esto es tarea? -

@Luchian Grigore: Cierto, compilará pero no hará lo que espera el OP. -

El código está mal formado porque structure no tiene constructor por defecto; el miembro de datos de tipo de referencia inhibe la declaración implícita de un constructor predeterminado (en C++ 11, su constructor predeterminado declarado implícitamente se define como eliminado). -

4 Respuestas

Si no puede usar un puntero, debe usar una referencia. Si usa una referencia, debe inicializarse a su valor final a medida que se construye.

struct structure
{
    BaseObject &A; //BaseObject has a function declared as virtual
    structure(BaseObject &A_) : A(A_) {}
};

DerivedObjectB *B = new DerivedObjectB(); 
structure *s = new structure(*B); //done
//keep in mind you cannot delete `B` until _after_ you delete `s`

Su código anterior no debería haberse compilado desde un structure no se pudo crear de esa manera ya que no tenía una estructura predeterminada automática ya que tiene un miembro de referencia. Además, incluso si compilara, el A miembro habría sido un BaseObject copia de los DerivedObjectBpadre BaseObject objeto, o algún otro extraño no-lo-que-querías.

¿Viajas absolutamente seguro ¿No puedes usar punteros allí? Eso no tiene ningún sentido y hace que sea muy difícil trabajar con esto.

Respondido el 12 de junio de 12 a las 19:06

No puede cambiar el objeto al que hace referencia A, una vez structure esta construido. Lo que probablemente le gustaría tener es:

struct structure
{
  structure() : A(NULL) {}
  ~structure() { if (this->A) { delete this->A; } }
  BaseObject * A;
};

structure *s = new structure;
s->A = new DerivedObjectB();

De todos modos, el uso de punteros sin procesar es propenso a errores y debe considerarlo.

Respondido el 12 de junio de 12 a las 18:06

Apuesto a que acabas de declarar

structure* s;

or

structure* s = NULL;

¿amirita? De lo contrario, no hay motivo para el bloqueo.

Or s->A hace referencia a un objeto que quedó fuera del alcance, por lo que cuando llama operator = en él te metes en un comportamiento indefinido.

Es uno de estos dos.

Respondido el 12 de junio de 12 a las 18:06

gracias por tu respuesta. Desde que inicialicé la estructura, supongo que es el segundo caso. - codereviewanskpreguntas

Esto ni siquiera debería compilar. La referencia no se puede volver a vincular después de la construcción, y debería haber recibido un error que le indica que debe haber estado vinculada a algo.

Respondido el 12 de junio de 12 a las 18:06

Ni siquiera está encuadernado en la construcción. - R. Martinho Fernández

@Greg O eso es un error o una extensión GNU (espero que no sea lo último). Prueba con un compilador más reciente y sin extensiones locas. - R. Martinho Fernández

Estoy tan sorprendido como tú. Explicación: gcc.gnu.org/bugzilla/show_bug.cgi?id=39045 - Greg

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.