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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.64
Den4ik
0 / 0 / 0
Регистрация: 24.08.2011
Сообщений: 42
#1

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

27.08.2011, 20:16. Просмотров 1745. Ответов 10
Метки нет (Все метки)

Есть абстрактный класс
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;}
};
Но вот с деструктором никак не разберусь. Выдает ошибку выделения памяти.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.08.2011, 20:16
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Абстрактный класс и использование деструктора (C++):

Использование деструктора - C++
Я не очень понимаю в каких случаях в классе или шаблоне надо реализовавывать дестрактор а в каких не не надо ??? вот например код : ...

Объяснить использование виртуального деструктора - C++
Ребят для чего здесь используется виртуальный деструктор? using namespace std; class Ostanovki { protected: char* name; ...

Использование деструктора в односвязном списке с++ - C++
Здравствуйте. Нужна срочная помощь!!! Есть реализация односвязного списка в котором узел - класс, а не структура. Вначале программы...

Использование объекта после вызова деструктора - C++
Здравствуйте. Вопрос, казалось бы, простой, но не могу найти точного ответа. class name { double* pD; public: name(); ...

Класс: Создать абстрактный базовый класс Figure с виртуальными методами вычисления площади и периметра. - C++
Создать абстрактный базовый класс Figure с виртуальными методами вычисления площади и периметра. Создать производные классы: Rectangle...

Абстрактный класс, наследование, класс хранится в другом классе - C++
Нужна помощь. Написать программу: 1 класс. Имеется абстрактный класс который описывает какую-то сущность, например Человек. В абстрактном...

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

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

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

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

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

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

Добавлено через 4 минуты
Цитата Сообщение от kravam Посмотреть сообщение
Ну и функции методы, содержащие исполнимый код (в данном случае, напомню, речь идёт о выделении памяти) определены и вызваны быть не могут.
Они могут быть вызваны из производных классов.
0
grizlik78
Эксперт С++
1911 / 1443 / 112
Регистрация: 29.05.2011
Сообщений: 3,000
28.08.2011, 00:25 #10
Если честно, то вообще непонятно, зачем создавать вектора динамически. Сделал бы v и e векторами, а не указателями, и удалять бы их не пришлось. Да и про элементы векторов тоже подумать стоит. Точно ли там должны быть указатели?
0
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;
    };
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.08.2011, 10:20
Привет! Вот еще темы с ответами:

Использование конструкторов и деструктора при проектировании пользовательского класса - C++
Дан одномерный массив A. Найти max (a2, a4, …, a2k) + min (a1, a3, …, a2k+1).

Создать класс и проверить работу конструктора и деструктора - C++
Вечер добрый! Собственно вопрос, нужно определить класс и создать конструктор, деструктор, указатель на экземпляр класса + определить в...

Создать абстрактный базовый класс Тройка чисел с виртуальными методами увеличения на 1. Создать производный класс Время со своими функциями - C++
Здравствуйте, пожалуйста помогите написать код к данной задаче, с таким условием: Создать абстрактный базовый класс Тройка чисел с...

Написать обработчик исключений ситуации при преобразовании указателя на класс B до указателя на абстрактный класс А ... - C++
Написать обработчик исключений ситуации при преобразовании указателя на класс B до указателя на абстрактный класс А ... как сделать...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
28.08.2011, 10:20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru