2

I wanted to implement a fixed size queue, I could have easily done with a struct having a queue as one of the data members and a member function that takes care of the push part of the queue, but rather wanted to try it out by inheriting queue like this.

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);
        }
    }
};

This compiles just fine but for some reason it gives a segmentation fault and the gdb says

Program received signal SIGSEGV, Segmentation fault. 0x0000555555555862 in std::_Deque_iterator<int, int&, int*>::_S_buffer_size() ()

Not really sure what that is supposed to mean? When tried doing a backtrace the output comes out to be

#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) ()

doesn't stop goes infinitely. Need help with this.Thanks in advance.

1
  • You introduced a recursion (probably unintended) with this->push(data);. I assume, you actually want queue<T>::push(data); to refer to push() of base class. Commented Aug 28, 2020 at 11:31

1 Answer 1

5

Your push function always recurses into itself:

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
        }
    }

You probably meant to call the base class's push:

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

Note that STL containers are not meant to be publicly derived from. They do not have virtual destructors, so make sure you never delete through the base class pointer/reference.

EDIT

Non-virtual destructor means the following code is dangerous:

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

There is no way how to force the call of the correct destructor. Making f_queue's destructor virtual will not help. But, as long as you never delete through a pointer to the base class, there is nothing wrong with deriving from any class.

One way to enforce that is to use private inheritance but I'm guessing you are using inheritance in the first place to retain most of the std::queue's API.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Quimby, just a question about destructor, you mentioned that STL containers don't have virtual destructor, so unless I am overriding the destructor for the base class (here queue) , there is no issues with this implementation right?
@Bad_Panda Expanded my answer. This has almost nothing with to do with override. And to be pedantic, destructors cannot be overriden, deleting a given class always calls all destructors of the base classes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.