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

Абстрактный класс - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 29, средняя оценка - 4.69
zhenya.ya
1 / 1 / 0
Регистрация: 29.11.2009
Сообщений: 304
03.11.2010, 22:31     Абстрактный класс #1
Есть базовый абстрактный класс. От него - 2 производных класса.
Проблемы: 1) Понимаю, что я не правильно вызываю мои чисто вирт. методы.Как правильно вызывать мои чисто вируальные методы(см. main )?
2) Как правильно должен быть организован деструктор в данном варианте?

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class base
{
public:
    int n;
    virtual void AddDate()=0;
    void WeightSort(); 
    void EndAddress(); 
    virtual void print()=0;
};
class first:public base
{
public:
     void AddDate();
    void print()
    {
        for(int i=0;i<n;i++)
        cout<<"naznachenie: "<<naznachenie[i]<<"; weight: "<<weight[i]<<endl;
    }
private:
    char **naznachenie;
    char *weight;
};
class second:public base
{
public:
     void AddDate();
    void print(){
        for(int i=0;i<n;i++)
            cout<<"name: "<<name[i]<<"; adress:"<<adress[i]<<endl;}
private:
    char **name;
    char *adress;
};
 
void first::AddDate()
{
    cout<<" how match:?"<<endl;
    cin>>n;
    char str[33];
    naznachenie = new char*[n];
    weight = new char[n];
    for(int i=0;i<n;i++)
    {
        cout<<"input naznachenie:"<<endl;
        cin>>str;
        naznachenie[i] = new char [strlen(str)+1];
        strcpy(naznachenie[i],str);
        cout<<"input weight:"<<endl;
        cin>>weight[i];
    }
}
void second::AddDate()
{
    char str1[33];
    name = new char*[n];
    for(int i=0;i<n;i++)
    {
        cout<<"input name:"<<endl;
        cin>>str1;
        name[i] = new char [strlen(str1)+1];
        strcpy(name[i],str1);
        cout<<"input adress"<<endl;
        cin>>adress[i];
    }
}
void main()
{
    first fst;
    fst.AddDate();
    fst.print();
    second snd;
    snd.AddDate();
    snd.print();
    system("PAUSE");
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.11.2010, 22:31     Абстрактный класс
Посмотрите здесь:

Написать обработчик исключений ситуации при преобразовании указателя на класс B до указателя на абстрактный класс А ... C++
C++ Абстрактный класс
C++ Абстрактный класс
C++ Создать класс - данные - абстрактный базовый класс. Создать производные классы
C++ Создать абстрактный базовый класс Тройка чисел с виртуальными методами увеличения на 1. Создать производный класс Время со своими функциями
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
patriot2008
 Аватар для patriot2008
70 / 70 / 4
Регистрация: 04.12.2008
Сообщений: 463
03.11.2010, 22:35     Абстрактный класс #2
Цитата Сообщение от zhenya.ya Посмотреть сообщение
first fst; fst.AddDate(); fst.print(); second snd;
надо так сделать
C++
1
2
3
4
5
6
7
8
first* fst = new first();
        fst->AddDate();
        fst->print();
        second* snd = new second();
        snd->AddDate();
        snd->print();
        delete first;
        delete second;
виртуальные методы будут вызваны правильно, так как надо использовать указатель на класс и динамически выделять память. Соответственно, надо будет удалять их через delete. Тогда деструкторы и сработают.
zhenya.ya
1 / 1 / 0
Регистрация: 29.11.2009
Сообщений: 304
03.11.2010, 23:13  [ТС]     Абстрактный класс #3
Т.е. , как я Вас понял, можно ли сделать так? :
C++
1
2
3
4
5
6
7
8
        first fst;
       base *p=&fst;
       p->AddDate();
       p->print();
       second snd;
       p = &snd;
       p->AddDate();
       p->print();
Да и думаю что у меня что-то не так с переменной n .
patriot2008
 Аватар для patriot2008
70 / 70 / 4
Регистрация: 04.12.2008
Сообщений: 463
04.11.2010, 01:12     Абстрактный класс #4
не правильно понял: память надо динамически выделять оператором new, а потом удалять с помощью delete. Если хочешь использовать базовый класс, то надо так:
C++
1
2
3
4
5
6
7
8
           first* fst = new first();
           base *p=fst;
           p->AddDate();
           p->print();
           second* snd = new second();
           p = snd;
           p->AddDate();
           p->print();
обьект абстрактного класса ты создать не можешь, создаем просто указатель на него. потом создаем два класса first и second динамически (только в этом случае будет работать полиморфизм). Если память выделять статически (как Вы делаете), то полиморфизма не будет.

Добавлено через 48 секунд
Цитата Сообщение от zhenya.ya Посмотреть сообщение
Да и думаю что у меня что-то не так с переменной n .
а переменную n нужно инициализировать перед тем как с ней работать.
volovzi
266 / 168 / 8
Регистрация: 14.03.2010
Сообщений: 501
04.11.2010, 01:49     Абстрактный класс #5
patriot2008, про виртуальные методы ты наврал. Можно хоть через ссылки их вызывать:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
struct A {
    virtual void show () const { std::cout << "A::show()" << std::endl; }
};
 
struct B : A {
    virtual void show () const { std::cout << "B::show()" << std::endl; }
};
 
int main (int argc, char * const argv[]) {
    B b;
    
    A & a = b;
    
    a.show();
 
    return 0;
}
Результат программы:
Код
B::show()
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
04.11.2010, 01:52     Абстрактный класс #6
zhenya.ya, Верно.
KpeHDeJIb
 Аватар для KpeHDeJIb
56 / 56 / 3
Регистрация: 31.10.2010
Сообщений: 103
04.11.2010, 01:55     Абстрактный класс #7
Цитата Сообщение от patriot2008 Посмотреть сообщение
обьект абстрактного класса ты создать не можешь, создаем просто указатель на него. потом создаем два класса first и second динамически (только в этом случае будет работать полиморфизм). Если память выделять статически (как Вы делаете), то полиморфизма не будет.
Неправда, полиморфизм и факт вызова конструкторов никак не зависит от способа выделения памяти. Всегда можно взять указатель на объект и привести указатель к указателю на базовый класс, после чего вызывая методы убедиться что полиморфизм отлично работает.

Цитата Сообщение от zhenya.ya Посмотреть сообщение
2) Как правильно должен быть организован деструктор в данном варианте?
Неправильно, деструктор базового класса надо объявить виртуальным, иначе при удалении объекта как указателя на базовый класс не будут вызваны правильные деструкторы (деструкторы наследуемых классов). В случае если один из наследников содержит динамически выделяемую память то ОБЯЗАТЕЛЬНО надо использовать виртуальный деструктор, в других случаях надо смотреть по обстоятельствам. Я вообще не люблю абстракции, поэтому десять раз подумаю пржде чем делать, но многие конторы в своих требованиях к разработчикам настоятельно рекомендуют деструктор базового класса всегда делать виртуальным.

Ну и кстати у тебя в наследниках выделяется память и нигде не освобождается, ты уж разберись.
volovzi
266 / 168 / 8
Регистрация: 14.03.2010
Сообщений: 501
04.11.2010, 02:05     Абстрактный класс #8
В добавление к словам Кренделя скажу, что виртуальность дектруктора обычно служит индикатором возможности его наследования, то есть если деструктор виртуален, то класс можно наследовать, в противном случае надо применять композицию.
Впрочем, это не предписание, а рекоммендация. Правило хорошего тона в программировании .
patriot2008
 Аватар для patriot2008
70 / 70 / 4
Регистрация: 04.12.2008
Сообщений: 463
04.11.2010, 18:29     Абстрактный класс #9
Цитата Сообщение от KpeHDeJIb Посмотреть сообщение
Неправда, полиморфизм и факт вызова конструкторов никак не зависит от способа выделения памяти.
это да, сорри, перепутал. думал о указателях, а говорил о выделении памяти. еще раз приношу извинения.
имелось в виду, что работать надо через ссылки и указатели для демонстрации работы виртуальных функций.
zhenya.ya
1 / 1 / 0
Регистрация: 29.11.2009
Сообщений: 304
04.11.2010, 23:13  [ТС]     Абстрактный класс #10
Если в сообщении номер 3 - я сделал правильно, то почему не доходит дело до вызова методав класса second
C++
1
2
3
4
...
 p = &snd;
 p->AddDate();
  p->print();
И как правильно делается делается вирт. деструктор ( закомментил свою попытку т.к. она явно не верна).
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
class base
{
public:
    int n;
    base(){n=0;}
    //virtual ~base();
    virtual void AddDate()=0;
    virtual void print()=0;
    void WeightSort(); 
    void EndAddress();
};
class first:public base
{
public:
    first(){naznachenie=NULL; weight=NULL;}
    //virtual ~first(){delete []naznachenie;for(int i=0;i<n;i++)delete []naznachenie[i];delete[]weight;}
    void AddDate();
    void print()
    {
        for(int i=0;i<n;i++)
        cout<<"naznachenie: "<<naznachenie[i]<<"; weight: "<<weight[i]<<endl;
    }
private:
    char **naznachenie;
    char *weight;
};
class second:public base
{
public:
    second(){adress=0;}
    //virtual ~second(){delete[]name;for(int i=0;i<n;i++)delete name[i]; delete []adress;
     void AddDate();
    void print(){
        for(int i=0;i<n;i++)
            cout<<"name: "<<name[i]<<"; adress:"<<adress[i]<<endl;}
private:
    char **name;
    char *adress;
};
 
    void first::AddDate()
{
    cout<<" how match:?"<<endl;
    cin>>n;
    char str[33];
    naznachenie = new char*[n];
    weight = new char[n];
    for(int i=0;i<n;i++)
    {
        cout<<"input naznachenie:"<<endl;
        cin>>str;
        naznachenie[i] = new char [strlen(str)+1];
        strcpy(naznachenie[i],str);
        cout<<"input weight:"<<endl;
        cin>>weight[i];
    }
}
void second::AddDate()
{
    char str1[33];
    name = new char*[n];
    for(int i=0;i<n;i++)
    {
        cout<<"input name:"<<endl;
        cin>>str1;
        name[i] = new char [strlen(str1)+1];
        strcpy(name[i],str1);
        cout<<"input adress"<<endl;
        cin>>adress[i];
    }
}
void main()
{
       first fst;
       base *p=&fst;
       p->AddDate();
       p->print();
       second snd;
       p = &snd;
       p->AddDate();
       p->print();
       system("PAUSE");
}
volovzi
266 / 168 / 8
Регистрация: 14.03.2010
Сообщений: 501
05.11.2010, 00:01     Абстрактный класс #11
zhenya.ya, должно быть всё правильно. Вот пример:
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
26
27
28
29
30
#include <iostream>
 
struct A {
    virtual ~A () {}
    
    virtual void show () const { std::cout << "A::show()" << std::endl; }
};
 
struct B : A {
    void show () const { std::cout << "B::show()" << std::endl; }
};
 
struct C : A {
    void show () const { std::cout << "C::show()" << std::endl; }
};
 
int main (int argc, char * const argv[]) {
    A * a;
    
    B b;
    C c;
    
    a = &b;
    a->show(); // Вывод — "B::show()"
    
    a = &c;
    a->show(); // Вывод — "C::show()"
    
    return 0;
}
А деструкторы действительно неверны. Во-первых, в базовом классе он должен быть таким:
C++
1
virtual ~base () {}
Во-вторых, в производных классах ты сначала удаляешь массив, а потом начинаешь удалять его содержимое. Здесь будет ошибка доступа к памяти. Нужно сделать всё наоборот.
KpeHDeJIb
 Аватар для KpeHDeJIb
56 / 56 / 3
Регистрация: 31.10.2010
Сообщений: 103
05.11.2010, 00:19     Абстрактный класс #12
Цитата Сообщение от zhenya.ya Посмотреть сообщение
И как правильно делается делается вирт. деструктор ( закомментил свою попытку т.к. она явно не верна).
В случае базового класса у тебя может быть пустой виртуальный деструктор, а вот в наследниках ты погорячился, вот в этом месте:
C++
1
2
3
4
5
6
7
virtual ~first()
{
    delete []naznachenie;
    for (int i=0;i<n;i++)
        delete []naznachenie[i];
        delete[]weight;
}
Правильно делать так:
C++
1
2
3
4
5
6
7
8
9
10
11
virtual ~first()
{
    for (int i = 0; i < n; i++)
        delete[] naznachenie[i];
 
    delete[] naznachenie;
    delete[] weight;
 
    naznachenie = NULL;
    weight      = NULL;
}
zhenya.ya
1 / 1 / 0
Регистрация: 29.11.2009
Сообщений: 304
05.11.2010, 00:55  [ТС]     Абстрактный класс #13
Огромное спасибо за помощь с деструкторами.
Но как понять проскакивание методов,связанных с second?? (т.е. все для fst выполняется и на этом все)
C++
1
2
3
4
5
6
7
8
9
10
base *p;
       first fst; second snd;
 
       p=&fst;
       p->AddDate();
       p->print();
      
       p = &snd;
       p->AddDate();
       p->print();
volovzi
266 / 168 / 8
Регистрация: 14.03.2010
Сообщений: 501
05.11.2010, 01:24     Абстрактный класс #14
zhenya.ya, у тебя всё правильно вызывается, просто в классе "second" у тебя не установлена переменная "n", поэтому функция ничего не делает.
zhenya.ya
1 / 1 / 0
Регистрация: 29.11.2009
Сообщений: 304
05.11.2010, 02:49  [ТС]     Абстрактный класс #15
А как можно сделать, чтобы ''n'' была общая для двух производных классов?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
05.11.2010, 03:22     Абстрактный класс #16
zhenya.ya,
C++
1
static int n
, если ничего не путаю.
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
05.11.2010, 04:34     Абстрактный класс #17
Цитата Сообщение от volovzi Посмотреть сообщение
А деструкторы действительно неверны. Во-первых, в базовом классе он должен быть таким:
C++
1
virtual ~base () {}
Может и таким быть
C++
1
virtual ~base ()  = 0 { /*....*/}
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
05.11.2010, 11:36     Абстрактный класс #18
ISergey,
Э.
C++
1
virtual ~base ()  = 0 { /*....*/}
Чисто виртуальный деструктор да еще и с определением? оО
volovzi
266 / 168 / 8
Регистрация: 14.03.2010
Сообщений: 501
05.11.2010, 12:27     Абстрактный класс #19
ISergey, Жжошъ!
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.11.2010, 14:36     Абстрактный класс
Еще ссылки по теме:

C++ Абстрактный класс
C++ абстрактный класс
Абстрактный класс/Класс интерфейс C++

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

Или воспользуйтесь поиском по форуму:
ISergey
Maniac
Эксперт С++
 Аватар для ISergey
1331 / 864 / 50
Регистрация: 02.01.2009
Сообщений: 2,622
Записей в блоге: 1
05.11.2010, 14:36     Абстрактный класс #20
ForEveR, volovzi,
Работает =)) (как ни странно )

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
class base{
public:
    virtual ~base() = 0;
};
 
class x: public base{
 
};
int main()
{
    x *r = new x;
 
    delete r;
    return 0;
}
 
base::~base(){
    std::cout << "O_o" << std::endl;
}
http://codepad.org/bGejuDXs
Yandex
Объявления
05.11.2010, 14:36     Абстрактный класс
Ответ Создать тему
Опции темы

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