2013-03-07 4 views
2
struct Abstract{ 
    virtual void methodA() = 0; 
}; 

struct Test : public Abstract{ 
    virtual void methodA(){ 
     printf("Test message"); 
    } 
}; 

class Foo{ 
    Abstract* abs; //I made it this way so that an instance of Foo 
        //can easily switch between any class that implements 
        //Abstract 
public: 
    virtual ~Foo(){ 
     delete abs; //free abs 
    } 

    void setAbs(Abstract* a){ 
     abs = a; //is there any other way to do this? 
    } 

    void changeAbs()//method to switch abs 

    void show(){ 
     abs->methodA(); 
    } 
}; 

int main(){ 
    Test *test = new Test(); 
// Test test; //local instantiation will throw a segmentation fault 
       //because abs is freed in the desctructor of Foo 
    Foo foo; 
    foo.setAbs(test); 
    foo.show(); 

// delete test; //using a pointer is fine unless freed 
    return 0; 
} 

Мои проблемы являются:Указатель и абстрактный класс

  1. Если я DonT свободный абс в деструкторе и пользователь забывает освободить свой объект, который реализует абстрактный или если пользователь сделать это таким образом setAbs(new Test()), будет утечка.

  2. Если я освобожу абс в деструкторе, он вызовет ошибку сегментации, если пользователь выполнит Тест локально, или он использует указатель и сам удаляет его.

  3. Abstract abs также не допускается, так как это абстрактный класс

Я хочу изменить setAbs() на что-то вроде этого:

void setAbs(Abstract* a){ 
    abs = new Abstract(*a); //but copying like a normal class doesn't work on abstract classes 
} 

мой вопрос, есть ли другой способ для реализации setAbs(), чтобы он передал копию аргумента?

Если нет другого способа, я просто позволю освободиться от работы пользователя.

+0

Uh, 'std :: shared_ptr'? –

+0

Обратите внимание, что 'Abstract' не имеет виртуального деструктора, поэтому' delete abs' вызывает неопределенное поведение. –

ответ

4

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

Если ваш класс владеет им, тогда можно безопасно освободить ваш деструктор. Ну, не так, как вы его написали, но теоретически. Читайте дальше: The Rule of Three.

Если ваш класс не собственный указатель, то, ну, не освобождайте его. Это не ваше освобождение, поэтому используйте его и больше не делайте.

Безопасный способ обработки памяти заключается в неявном соблюдении контракта относительно того, кто несет ответственность за что. Если пользователь идет вперед и delete с указателем, ну, скажите им остановиться; это не их дело. Вы можете сделать то же самое с помощью указателя std::unique_ptr и функции get(). Класс не остановит вас, как он мог? Не важно, стреляете ли вы с собственной ноги. RTFM.

Разговор о std::unique_ptr ... почему вы не используете его (или std::shared_ptr, если необходимо)? Это решаемая проблема, и вам не нужно придумывать свое решение.

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