2014-01-05 4 views
1

Я новичок в C++ и изучаю виртуальные функции и узнал, что мы должны писать виртуальный деструктор, если класс имеет виртуальные функции, а класс имеет элементы указателя. Ниже мой код, и я с помощью виртуальной студии 2013RCОтладка Утверждение Сбой при попытке удалить char *

#include<iostream> 

using namespace std; 
//base and derived class with virtual function 
class Parent{ 
protected: 
    const char *name; 
public: 
    virtual void say(){ cout << "1" << endl; } 
    virtual void showName(){ cout << name << endl; } 
    Parent(){}; 
    Parent(const char *myName) :name(myName){}; 
    virtual ~Parent(){ delete name; cout << "Parent name deleted" << endl; } 
}; 

class Child :public Parent{ 
protected: 
    const char *name; 
public: 
    virtual void say(){ cout << "2" << endl; } 
    virtual void showName(){ cout << name << endl; } 
    Child(){}; 
    Child(const char *myName) :name(myName){}; 
    virtual ~Child(){ delete name; cout << "Child name deleted" << endl;} 
}; 

int main(){ 
    Child a("Tom"); 
    return 0; 
} 

Или

int main(){ 
    Parent *a = new Child("Tom"); 
    delete a;   
    return 0; 
} 

Оба будут давать окна об ошибках Debug утверждения Failed. enter image description here

Для этого случая, как правильно записать виртуальный деструктор?

Большое спасибо

ответ

5

Потому что вы пытаетесь удалить буквального указатель на строку. Вы устанавливаете член Child::name для указания на строчную строку "Tom", которая является указателем на память, созданным вашим компилятором. Вы должны только delete, что вы явно new.

Также обратите внимание, что классы Parent и Child имеют разные и различные переменные-члены name. Когда вы инициализируете переменную Child::name, то в Parent по-прежнему неинициализируется.

0

Вы пытаетесь удалить указатель char, который не является сложным объектом. Простое базовое правило: для каждого new для освобождения памяти должно быть delete.

В вашем случае вы пытаетесь освободить const char.

1

При написании:

Parent *a = new Child("Tom"); 

строка "Tom" определяется как буквальное, это означает, что это базовый блок, как 0-9, например, если вы посмотрите на свой исполняемый файл вы можете найти его там, они являются окончательными и вы не можете изменить их каким-либо образом (например, вы не можете переопределить 1 на 2).

Вы не можете изменить литералы, поэтому чередующийся строковый литерал каким-либо образом (например, delete) вызовет ошибки и ошибки сегментации, поскольку это похоже на изменение собственного исполняемого файла, который вы сейчас используете (исполняемый файл не имеет этих разрешений).

+0

Thanks @Vladp. Я прочитал приведенный ниже код из книги 'int foo = 10; int * ptr = foo; delete ptr; ' Кажется, что это тоже не работает ... – cgao

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