Quería implementar una cola de tamaño fijo, podría haberlo hecho fácilmente con una estructura que tiene una cola como uno de los miembros de datos y una función de miembro que se encarga de la parte de inserción de la cola, pero quería probarlo heredando cola como esta.

template<typename T>
struct f_queue : public queue<T>{
    int n;
    T prev;

    f_queue(int n_):
        n(n_){}

    void push(T data){
        if(this->size() < this->n){
            this->push(data);
        }else{
            prev = this->front();
            this->pop();
            this->push(data);
        }
    }
};

Esto se compila bien, pero por alguna razón da una falla de segmentación y el gdb dice

Programa recibido señal SIGSEGV, Fallo de segmentación. 0x0000555555555862 en std :: _ Deque_iterator :: _ S_buffer_size () ()

¿No estás seguro de lo que se supone que significa eso? Cuando se intenta hacer un rastreo hacia atrás , el resultado resulta ser

#9913 0x0000555555554ec6 in f_queue<int>::push(int) ()
#9914 0x0000555555554ec6 in f_queue<int>::push(int) ()
#9915 0x0000555555554ec6 in f_queue<int>::push(int) ()
#9916 0x0000555555554ec6 in f_queue<int>::push(int) ()
#9917 0x0000555555554ec6 in f_queue<int>::push(int) ()
#9918 0x0000555555554ec6 in f_queue<int>::push(int) ()
#9919 0x0000555555554ec6 in f_queue<int>::push(int) ()

No se detiene va infinitamente. Necesito ayuda con esto Gracias de antemano.

2
Bad_Panda 28 ago. 2020 a las 14:21

1 respuesta

La mejor respuesta

Su función de empuje siempre recurre a sí misma:

void push(T data){
        if(this->size() < this->n){
            this->push(data);//HERE f_queue::push is called
        }else{
            prev = this->front();
            this->pop();
            this->push(data);//HERE f_queue::push is called
        }
    }

Probablemente quisiste llamar al empuje de la clase base:

void push(T data){
        if(this->size() < this->n){
            queue<T>::push(data);
        }else{
            prev = this->front();
            this->pop();
            queue<T>::push(data);
        }
    }

Tenga en cuenta que los contenedores STL no deben derivarse públicamente de. No tienen destructores virtuales, así que asegúrese de nunca eliminar a través del puntero / referencia de clase base.

EDITAR

El destructor no virtual significa que el siguiente código es peligroso:

std::queue<T>* base = new f_queue<T>();
delete base;//Call std::queue<T>::~queue();

No hay forma de forzar la llamada del destructor correcto. Hacer virtual el destructor de f_queue no ayudará. Pero, siempre que nunca elimine a través de un puntero a la clase base, no hay nada de malo en derivar de ninguna clase.

Una forma de hacer cumplir eso es usar la herencia privada, pero supongo que está usando la herencia en primer lugar para retener la mayor parte de la API de std::queue.

5
Quimby 29 ago. 2020 a las 13:08