Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/25: Рейтинг темы: голосов - 25, средняя оценка - 4.80
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 36
1

Наследование - вызов конструкторов и деструкторов

01.11.2015, 02:04. Показов 4425. Ответов 53
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Делаю два класса - предок и потомок:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class class_1_type {
private:
    int t;
public:
    class_1_type(int t_) { t = t_; cout << "class_1. object: " << this << " - constructor  t = " << t << endl; }
    ~class_1_type() { cout << "class_1. object: " << this << " - destructor  t = " << t << endl; }
};
 
 
class class_2_type: public class_1_type {
private:
    int s;
public:
    class_2_type(int t_, int s_): class_1_type(t_) { s = s_; cout << "class_2. object: " << this << " - constructor  s = " << s << endl; }
    ~class_2_type() { cout << "class_2. object: " << this << " - destructor  s = " << s << endl; }
};
Пишу такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
    class_1_type * ob1;
    class_2_type * ob2;
 
    ob1 = new class_1_type(1);
    delete ob1;
 
    ob1 = new class_2_type(2, 3);
    delete ob1;
 
    ob2 = new class_2_type(4, 5);
    delete ob2;
Получаю такой вывод на экран:
class_1. object: 00343AF8 - constructor t = 1
class_1. object: 00343AF8 - destructor t = 1

class_1. object: 00343AF8 - constructor t = 2
class_2. object: 00343AF8 - constructor s = 3
class_1. object: 00343AF8 - destructor t = 2

class_1. object: 00343AF8 - constructor t = 4
class_2. object: 00343AF8 - constructor s = 5
class_2. object: 00343AF8 - destructor s = 5
class_1. object: 00343AF8 - destructor t = 4
Первый и третий случаи - все понятно.
Подскажите пожалуйста, почему во втором случае не вызвался деструктор класса-наследника??
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.11.2015, 02:04
Ответы с готовыми решениями:

Вызов конструкторов/деструкторов при наследовании
Объясните пожалуйста, как получается вывод на экран 2531 #include &lt;iostream&gt; class A {...

Вызов лишних конструкторов и деструкторов в std::vector
почему вызывает лишние конструкторы и вообще делает не то, что ожидаешь class S { public: int...

Задание с использованием конструкторов и деструкторов
Нужна ваша помощь. Само задание: Разработать класс - СТУДЕНТ. В закрытой части определить данные:...

Порядок вызова конструкторов/деструкторов
Вопрос чисто теоретический. Попробую сформулировать, не ругайте если получится коряво. Например,...

53
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 14:10 41
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от mporro Посмотреть сообщение
Чтобы корректно унаследоваться мне достаточно информации об открытом контракте, которая у меня уже есть.
Потому внедрение protected контракта -- это уже излишне. Зачем?
вы ж не от сферического вакуума наследуетесь.

кто-то разработал базовый класс, заложив основу - дизайн.
и, например, он определил ряд виртуальных функций-членов
специально предназначенных для определения в наследниках.

зачем это было нужно зависит от конкретной ситуации.

Цитата Сообщение от mporro Посмотреть сообщение
Печально, что и это не всегда правда.
это - с++. здесь полным полно подобных нюансов.

хорошая новость в том,
что на практике подобного рода грабельки жить не мешают.

Цитата Сообщение от mporro Посмотреть сообщение
Итог: вместо того, чтобы втыкать только в открытый интерфейс, как с обычным наследованием, я должен ещё и разобрать защищённый.
ну вот я например, втыкаю только в прототипы.
детали реализации чужого класса меня не интересуют
(настолько, насколько это вообще возможно в несовершенном мире).

с другой стороны, я не дергаю функционал базы в конструкторе своего наследника.
обычно в этом просто нет необходимости.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 14:38 42
hoggy
Дело в том, что если нужно манипулировать именно поведением, то наследование избыточный механизм, потому что ещё и навешивает типовую метку. Если же NVI подразумевает создание подтипа, то неизбежно расширенный класс столкнётся с тем, что нужно детально знать базовый контракт, иначе легко провалить аксиоматику подтипа.

В итоге: NVI не спасает от проблем наследования, но работа с открытыми виртуальными методами всегда более прозрачная.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 16:44 43
Цитата Сообщение от mporro Посмотреть сообщение
если нужно манипулировать именно поведением, то наследование избыточный механизм
особенность механизма наследования:
он практичен, что значит прост в эксплуатации

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

например вот этот код:

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
#include <iostream>
 
struct Base
{
    std::ostream& hello(std::ostream& stream)const
    {
        concrete_hello(stream);
        return stream;
    }
protected:
    virtual void concrete_hello(std::ostream&)const = 0{};
};
 
struct Derived : Base
{
    Derived(std::ostream& stream)
    {
        Base::hello(stream);
    }
protected:
    virtual void concrete_hello(std::ostream&)const = 0;
};
 
 
struct NextDerived : Derived
{
    NextDerived(std::ostream& stream) : Derived(stream){}
protected:
    virtual void concrete_hello(std::ostream& stream)const
    {
        stream << "Hello, NextDerived" << std::endl;
    }
};
 
int main()
{
    std::cout << "hello, world\n";
    NextDerived nextDerived(std::cout);
}
успешно собрался компилятором от msvc2013:
hello, world
Hello, NextDerived
вопрос: почему процесс не упал на вызове чисто виртуальной функции?
ответ: потому что никаких виртуальных вызовов и не было.
компилятор сумел оптимизировать виртуальный вызов до прямого.

скажем так... с классическим паттерном "стратегия" у компиляторов все намного печальнее.

можно ещё применить статическую стратегию на шаблонах.
пожалуй это будет эффективно.
но это уже тяжелая артиллерия.
шаблоно-магия не всегда приемлема.

Цитата Сообщение от mporro Посмотреть сообщение
NVI не спасает от проблем наследования
а он и не предназначен для этой цели.

NVI - это тупо "фабричный метод".
наследники реализуют лишь мелкие не сильно значащие детальки.
а основняк крутится в базе,
и лишь время от времени тыркает наследников "уточнить мелочовку".

и потом, что такое вообще "проблемы наследования" ?
если речь идет о том,
что приходится вникать в детали базовых классов,
то это проблема их дизайна,
а вовсе не наследования, как такового.

можно же сделать так, что и не придется.
это зависит от конкретных ситуаций,
и конкретных классов.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 17:27 44
Цитата Сообщение от hoggy Посмотреть сообщение
успешно собрался компилятором от msvc2013
А под Debian собранный с использованием gcc и Windows10 vs 2015 получается Segmentaion Fault в релизе. В дебаге vs 2015 даёт pure virtual function call.

Цитата Сообщение от hoggy Посмотреть сообщение
наследники реализуют лишь мелкие не сильно значащие детальки
Если речь только "о детальках реализации", то почему не стратегии Александреску?
Открытое наследование ещё и прицепит новый тип, по существу создаст новый контракт.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 17:58 45
Цитата Сообщение от mporro Посмотреть сообщение
то почему не стратегии Александреску?
вы не особенно внимательный:
Цитата Сообщение от hoggy Посмотреть сообщение
можно ещё применить статическую стратегию на шаблонах.
пожалуй это будет эффективно.
но это уже тяжелая артиллерия.
шаблоно-магия не всегда приемлема.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 18:10 46
Цитата Сообщение от hoggy Посмотреть сообщение
вы не особенно внимательный
Возможно.
Но и Вы на вопрос не ответили.
Ваш код под стратегии Александреску можно и без шаблонов переделать.
Почему не стратегии?
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 18:19 47
Цитата Сообщение от mporro Посмотреть сообщение
Ваш код под стратегии Александреску можно и без шаблонов переделать.
Почему не стратегии?
а зачем?
в отдельных ситуациях они - то, что доктор прописал.
но они более сложны в плане понимания и эксплуатации.

к тому же, они никак не избавят вас от ваших проблем с наследованием.
просто раньше вам приходилось втыкать в базовый класс.
а теперь - в класс стратегии.
те же яйца, только сбоку.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 18:30 48
Цитата Сообщение от hoggy Посмотреть сообщение
просто раньше вам приходилось втыкать в базовый класс.
Со стратегиями мне уже действительно не приходится задумываться о "базовом классе", просто потому что у меня нет "базового класса". NVI подразумевает наследование и основного интерфейса, и интерфейса деталей реализации. То есть NVI вдвое сложнее.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 18:35 49
Цитата Сообщение от mporro Посмотреть сообщение
Со стратегиями мне уже действительно не приходится задумываться о "базовом классе", просто потому что у меня нет "базового класса"
не факт.

Цитата Сообщение от mporro Посмотреть сообщение
NVI подразумевает наследование и основного интерфейса, и интерфейса деталей реализации.
NVI подразумевает, что вам нужно вдуплять только в мелкие частности,
которые определяет наследник.

что такое "интерфейс деталей реализации" мне не понятно.
однако сама фраза содержит внутреннее противоречие.
следует отделять понятие интерфейса от деталей реализации,
которые он инкапсулирует.
0
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 36
09.11.2015, 10:22  [ТС] 50
Цитата Сообщение от Fallenworld Посмотреть сообщение
конструктор сам вызывает консруктор базового класса. И только без параметров. Все остальное надо пилить самому
Тогда так:
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
#include <iostream>
using namespace std;
 
 
 
class hierarchy_level_1 {
public:
    hierarchy_level_1() {cout << "hierarchy_level_1. costructor." << endl; }
    ~hierarchy_level_1() {cout << "hierarchy_level_1. destructor." << endl; }
};
 
 
class hierarchy_level_2: public hierarchy_level_1 {
public:
    hierarchy_level_2() {cout << "hierarchy_level_2. costructor." << endl; }
    ~hierarchy_level_2() {cout << "hierarchy_level_2. destructor." << endl; }
};
 
void main() {
    cout << endl << endl; 
 
    hierarchy_level_1 *ob1 = new hierarchy_level_2;
    delete ob1;
 
    cout << endl << endl; system("pause");
}
Выдает:
hierarchy_level_1. costructor.
hierarchy_level_2. costructor.
hierarchy_level_1. destructor.
И опять - оба конструктора вызвались, а деструкторов вызвалось только один.
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
09.11.2015, 10:45 51
Поздравляю тебя, шарик. Всю первую страницу писали про виртуальные деструкторы, но ты так и не понял...
0
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 36
09.11.2015, 12:38  [ТС] 52
Цитата Сообщение от castaway Посмотреть сообщение
Поздравляю тебя, шарик. Всю первую страницу писали про виртуальные деструкторы, но ты так и не понял...
тузик, расскажи нам про свое понимание, например, этого:

C++
1
2
3
4
    ...........
    hierarchy_level_2 *ob1 = new hierarchy_level_2;
    delete ob1;
    ...........
hierarchy_level_1. costructor.
hierarchy_level_2. costructor.
hierarchy_level_2. destructor.
hierarchy_level_1. destructor.
Ну что, эксперд нам расскажет как в этом примере вызываются виртуальные деструкторы????



Но, кажется, я и без экспертов понял в чем дело...
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
09.11.2015, 13:23 53
Цитата Сообщение от m45 Посмотреть сообщение
Но, кажется, я и без экспертов понял в чем дело...
Аллилуйя, ёп-т.
0
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 36
09.11.2015, 19:07  [ТС] 54
Цитата Сообщение от castaway Посмотреть сообщение
Аллилуйя, ёп-т.
Аминь, чо.
0
09.11.2015, 19:07
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.11.2015, 19:07
Помогаю со студенческими работами здесь

Правильное использование конструкторов и деструкторов
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace std; class Worker...

Разработка классов, создание конструкторов и деструкторов
Здравствуйте, помогите решить следующее задание: Постpоить класс для pаботы со cтpоками. Класс...

Ошибки в программе с использованием конструкторов/деструкторов
Приветы Есть код: #include &lt;iostream&gt; #include &lt;cmath&gt; #include &lt;stdlib.h&gt;

Как реализовать набор конструкторов и деструкторов
Делаю так: #include &lt;iostream&gt; class Time //начало объявления класса { public: //начало...


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

Или воспользуйтесь поиском по форуму:
54
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru