Форум программистов, компьютерный форум CyberForum.ru

Абстрактный класс и использование деструктора - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.64
Den4ik
0 / 0 / 0
Регистрация: 24.08.2011
Сообщений: 42
27.08.2011, 20:16     Абстрактный класс и использование деструктора #1
Есть абстрактный класс
C++
1
2
3
4
5
6
7
8
9
10
11
template <class Vertex, class Edge> class ABCG
{
protected:
    vector <Vertex *> *v;
    vector <Edge *> *e;
public:
    virtual ~ABCG (){};
           virtual Vertex* InsertV( ) = 0;  
    virtual Vertex* InsertV(Vertex* v) = 0; 
    virtual bool DeleteV (Vertex* v) = 0;
};
У него два наследника: L-граф и M-граф.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template <class Vertex, class Edge> class LGraph: public ABCG <Vertex, Edge> 
{
private: 
    vector<list<Edge *>> Adjlist;
    bool directed;
    int cnt_v, cnt_e;
public: 
    LGraph()
    {
        cnt_v = 0; cnt_e = 0;
        directed = false;
        v = new vector<Vertex*>;
        e = new vector<Edge*>;
    };
    LGraph (int _v, bool _D )
    {
        cnt_v = _v; cnt_e = 0;
        v = new vector<Vertex*>;
        e = new vector<Edge*>;
        directed = _D;
        for(int i = 0; i < _v; i++)
            InsertV();
    };
    ~LGraph(){delete e, v, Adjlist; };
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template <class Vertex, class Edge> class MGraph: public ABCG <Vertex, Edge>
{
private:
    bool directed;
           vector<vector<Edge*>> matrix;
    int cnt_v, cnt_e;
public: 
    MGraph()
    {
        cnt_v = 0; cnt_e = 0;
        directed = false;
        v = new vector<Vertex*>;
        e = new vector<Edge*>;
    };
    MGraph (int _v, bool _D )
    {
        cnt_v = _v; cnt_e = 0;
        v = new vector<Vertex*>;
        e = new vector<Edge*>;
        for(int i = 0; i < _v; i++)
            InsertV();
        directed = _D;
    };
    ~MGraph(){delete e, v, matrix;}; 
};
Есть класс Граф. В его конструкторе есть указатель на этот абстрактный класс, и инициализируется либо list, либо matrix графом

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <class Vertex, class Edge> class Graph
{
protected:
    ABCG <Vertex, Edge> *abstr;
public:
    Graph() 
    {
        abstr = new LGraph<Vertex, Edge>();
    };
 
    Graph (int _V, bool _D, bool _T)
    {
        if(_T == LGRAPH) 
            abstr = new LGraph<Vertex, Edge>(_V, _D);
        else
            abstr = new MGraph<Vertex, Edge>(_V, _D);
 
    };
           ~Graph (){delete abstr;}
};
Но вот с деструктором никак не разберусь. Выдает ошибку выделения памяти.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.08.2011, 20:16     Абстрактный класс и использование деструктора
Посмотрите здесь:

C++ абстрактный класс
Абстрактный класс C++
C++ Абстрактный класс
Использование деструктора C++
C++ Использование конструкторов и деструктора при проектировании пользовательского класса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
27.08.2011, 20:22     Абстрактный класс и использование деструктора #2
Цитата Сообщение от Den4ik Посмотреть сообщение
C++
1
~LGraph(){delete e, v, Adjlist; };
Это должно выглядеть так:
C++
1
~LGraph(){delete e; delete v; };
Нельзя их всех удалить одним вызовом delete.
А Adjlist и вовсе не надо удалять. Можно только удалить его элементы, но с ходу не понятно, надо ли.
Ну и по другим аналогично.
Сыроежка
Заблокирован
27.08.2011, 20:29     Абстрактный класс и использование деструктора #3
У вас вообще неправильный дизайн классов. Каждый должен отвечать за то, чем он владеет и не лезть туда, где начинается компетенция других. Это означает, что вы в своем базовом классе должны объявить конструктор, который создает ваши векторы, а также деструктор, который их удаляет. То есть не в производных классах это делать, а именно в базовом классе, так как эти указатели на вектора принадлежат базовому классу.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
27.08.2011, 20:34     Абстрактный класс и использование деструктора #4
Ой, я даже и не посмотрел, что указатели из базового класса. Жуть какая.
Den4ik
0 / 0 / 0
Регистрация: 24.08.2011
Сообщений: 42
27.08.2011, 20:35  [ТС]     Абстрактный класс и использование деструктора #5
)) спасиб
Сыроежка
Заблокирован
27.08.2011, 20:36     Абстрактный класс и использование деструктора #6
Цитата Сообщение от Den4ik Посмотреть сообщение
Это да, стыдно за такую ошибку... Но проблемки это не решило, все также. Получается деструкторы и не использовались?
Вы покажите переписанный код по новому дизайну, и тогда будем обсуждать его дальше.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,268
27.08.2011, 22:53     Абстрактный класс и использование деструктора #7
Сыроежка, именно "Каждый должен отвечать за то, чем он владеет и не лезть туда, где начинается компетенция других." Сие определяет автор. А коль скоро так, то почему бы не сделать абстрактный класс сугубо интерфейсным, не возлагая на него других функций, как-то: выделения памяти и освобождения памяти.

Последнее рационально и вот по какой причине: производные классы могут создаваться, например в цикле, в функции какой-нибудь и прочая. А тогда память, отведённая под вектора их конструкторах будет освобождаться деструкторами при выходе из области видимости. Довольно стройное на мой взгляд решение освобождения памяти.
Иначе, если память выделить в базовом классе (в нашем случае ABCG), так и будет "висеть", пока или программа не закончится или... Или как-то принудительно не будет вызван деструктор базового класса. Извините.

Добавлено через 1 минуту
И вообще хочется увидеть уже main

Добавлено через 10 минут
И ещё одно: челу позарез необходим именно абстрактный класс. Ладно, щас с ходу пытался ответить на вопрос и не смог: а как вообще в абстрактном классе может быть реализован какой-либо код? Объект этого класса создан быт не может. Значит, о вызове конструктора можно забыть. Ну и функции методы, содержащие исполнимый код (в данном случае, напомню, речь идёт о выделении памяти) определены и вызваны быть не могут. Так что если нужен именно абстрактный кллас, то всё это надо делегировать производным (что и было сделано). Извините если что не так.
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2293 / 1663 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
27.08.2011, 23:26     Абстрактный класс и использование деструктора #8
Цитата Сообщение от kravam Посмотреть сообщение
А коль скоро так, то почему бы не сделать абстрактный класс сугубо интерфейсным, не возлагая на него других функций, как-то: выделения памяти и освобождения памяти.
Ага, даешь дублирование кода во всех производных классах.
Цитата Сообщение от kravam Посмотреть сообщение
а как вообще в абстрактном классе может быть реализован какой-либо код?
См. выше.
Цитата Сообщение от kravam Посмотреть сообщение
Довольно стройное на мой взгляд решение освобождения памяти.
Ага, через ж*пу.

kravam, Вы вообще в курсе, что дублирование кода - проблема №1 в индустрии разработки ПО?

Den4ik, зачем вы удалеете поля через delete, если они не были выделены с помощью new?
Net_Wanderer
235 / 208 / 19
Регистрация: 08.06.2011
Сообщений: 467
28.08.2011, 00:20     Абстрактный класс и использование деструктора #9
Цитата Сообщение от kravam Посмотреть сообщение
Объект этого класса создан быт не может. Значит, о вызове конструктора можно забыть.
При конструировании обьекта класса, который был унаследован от абстрактного, сначала будет вызван конструктор абстрактного а потом производного.

Добавлено через 4 минуты
Цитата Сообщение от kravam Посмотреть сообщение
Ну и функции методы, содержащие исполнимый код (в данном случае, напомню, речь идёт о выделении памяти) определены и вызваны быть не могут.
Они могут быть вызваны из производных классов.
grizlik78
Эксперт C++
 Аватар для grizlik78
1882 / 1414 / 101
Регистрация: 29.05.2011
Сообщений: 2,958
28.08.2011, 00:25     Абстрактный класс и использование деструктора #10
Если честно, то вообще непонятно, зачем создавать вектора динамически. Сделал бы v и e векторами, а не указателями, и удалять бы их не пришлось. Да и про элементы векторов тоже подумать стоит. Точно ли там должны быть указатели?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.08.2011, 10:20     Абстрактный класс и использование деструктора
Еще ссылки по теме:

Абстрактный класс/Класс интерфейс C++
Объяснить использование виртуального деструктора C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Den4ik
0 / 0 / 0
Регистрация: 24.08.2011
Сообщений: 42
28.08.2011, 10:20  [ТС]     Абстрактный класс и использование деструктора #11
Ну а если убрать из абстракного класс динамические вектора и сделать так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <class Vertex, class Edge> class LGraph: public ABCG <Vertex, Edge> 
{
private: 
        vector <Vertex *> v;
        vector <Edge *> e;
        vector<list<Edge *>> Adjlist;
        bool directed;
        int cnt_v, cnt_e;
public: 
        LGraph()
        {
                cnt_v = 0; cnt_e = 0;
                directed = false;
        };
Как я понял деструктор и не нужен будет.


И в векторах должны быть указатели на элементы.

Добавлено через 2 часа 5 минут
Хотя в абстрактном классе нужны вектора(не динамические) так как есть метод с помощью которого можно изменить представление(Л или М граф)
C++
1
2
3
4
5
6
7
8
9
template <class Vertex, class Edge> class ABCG
{
protected:
    vector <Vertex *> v;
    vector <Edge *> e;
public:
    virtual ~ABCG (){};
virtual void fromAbstract(vector<Vertex *> v, vector<Edge *> e, bool d) = 0; //ОК
};
в классе М-графа переоределен так.
C++
1
2
3
4
5
6
7
8
9
10
11
void fromAbstract(vector <Vertex *> v, vector <Edge *> e, bool d)
    {
        this->v.clear();
        this->e.clear();
        this->directed = d;
        matrix.clear();
        for(unsigned int i = 0; i < v.size(); i++)
            InsertV(v.at(i));
        for(unsigned int i = 0; i < e.size(); i++)
            InsertE(e.at(i)->from, e.at(i)->to);
    };
В Л так же

А в простом графе вызывается в двух методах меняющих представление графа
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void ToListGraph()                  //преобразует граф к L- графу,
    {
        if(abstr->Dense() == LGRAPH) return;
        vector<Vertex*> v = abstr->getVertexesVector();
        for(vector<Vertex*>::iterator it = v.begin();it != v.end(); it++)
                (*it)->index = -1;
        vector<Edge *> e = abstr->getEdgesVector();
        for(typename vector<Edge*>::iterator it = e.begin(); it != e.end(); it++) (*it)->index = -1;
        bool d = abstr->Directed();
        abstr = new LGraph<Vertex, Edge>(0, d);
        abstr->fromAbstract(v, e, d);
    //  delete v, e;
    };                              
    void ToMatrixGraph()                 //преобразует граф к M- графу,
    {
        if(abstr->Dense() == MGRAPH) return;
        vector<Vertex*> v = abstr->getVertexesVector();
        for(vector<Vertex*>::iterator it = v.begin(); it != v.end(); it++) (*it)->index = -1;
        vector<Edge *> e = abstr->getEdgesVector();
        for(typename vector<Edge*>::iterator it = e.begin(); it != e.end(); it++) (*it)->index = -1;
        bool d = abstr->Directed();
        abstr = new MGraph<Vertex, Edge>(0, d);
        abstr->fromAbstract(v, e, d);
        //delete v, e;
    };
Yandex
Объявления
28.08.2011, 10:20     Абстрактный класс и использование деструктора
Ответ Создать тему
Опции темы

Текущее время: 21:50. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru