2013-03-15 22 views
0

я следующий код:C++ удалить указатель производного класса, который присваивается указатель базового класса

/* Example OOPBEI03.CPP */ 
#include <iostream> 

using namespace std; 

typedef char item; 

class stack 
{ 
private: 
    int p; 
protected: 
    item *st; 
public: 
    stack(int m=100) 
    { 
     st = new item[m]; 
     p = 0; 
    } 

    ~stack() 
    { 
     delete [] st; 
    } 

    void push(item v) 
    { 
     st[p++] = v; 
    } 

    item pop() 
    { 
     return st[--p]; 
    } 

    int empty() 
    { 
     return !p; 
    } 
}; 

class queue : public stack 
{ 
private: 
    int q; 
    item *qp; 
public: 
    queue(int m=50):stack(m) 
    { 
     q = 0; 
     qp = st; 
    } 

    ~queue() 
    { 
     delete qp; 
    } 

    item deque() 
    { 
     return qp[q++]; 
    } 
}; 

int main() 
{ 
    stack s(50); 
    queue q(20); 

    s.push('a'); 
    q.push('b'); 
    s.push('c'); 
    q.push('d'); 

    cout<<"pop "<<s.pop()<<endl; 
    cout<<"pop "<<s.pop()<<endl; 
    cout<<"deque "<<q.deque()<<endl; 
    cout<<"deque "<<q.deque()<<endl; 
    cout<<"empty queue? "<<q.empty()<<endl; 
    cout<<"empty stack? "<<s.empty()<<endl; 

    getchar(); 
    return 0; 
} 

я получаю в конце основного() в Visual Studio следующее сообщение об ошибке: «Debug Assertion Ошибка! ... _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse) ".

Если я раскомментирую операцию удаления либо в деструкторе очереди классов, либо в стеке (я раскомментирую только одну операцию!), У меня нет проблем.

Как я могу это решить?

+1

Я не вижу правило трех/пяти соблюдаются. – chris

+2

Сначала прочитайте о «виртуальных» деструкторах, затем о [правиле трех] (http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29) и, наконец, подумайте о том, что происходит, когда вы пытаетесь чтобы освободить указатель дважды. –

+0

@all: Спасибо за ваши ответы. Проблема в том, что этот код находится в моей учебной книге. Сейчас я изучаю C++ в школе. –

ответ

1

Удаление qp Должен ли я такой же, как новый (это мой термин))).

delete [] qp; 
     ^^ 

Но в данном случае удаление qp должны быть удалены на всех

+0

'delete []' в классе 'stack', похоже, уже имеет эту форму. –

1

Вы удаляете указатель как в базовом классе стека, так и в производном классе очереди.

пусть ваш класс стека обрабатывать собственности, не удаляйте его также в очереди

по пути вы должны сделать конструкцию копий и назначение частных, или же справиться с этим (известный как «правило трех»); в противном случае эти классы могут быть легко использованы в ungood способами ...


в коде, который не только для обучения, просто использовать std::stack и std::queue вместо реализации таких классов себя

std::stack и std::queue относятся к классу шаблоны с настраиваемым базовым контейнером типа

+0

На самом деле, только деструктор очереди вызывается, потому что конструктор стека не является виртуальным. Он терпит неудачу, потому что он должен использовать delete [] qp. Но я согласен с тем, что было бы лучше сделать виртуальный дескриптор стека и позволить ему обрабатывать удаление. –

+0

@ KristianDuske: как насчет того, чтобы попробовать такие вещи перед публикацией? ;-) Не то, что результаты с данным компилятором - это любые * гарантии *, которые соответствуют стандартным требованиям, но это очень наводящий на размышления. –

+0

Извините, вы правы. Оба дескриптора вызываются. Я буду уверен, что мои комментарии на самом деле верны в будущем! –

Смежные вопросы