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

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

Восстановить пароль Регистрация
 
 
m45
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 22
01.11.2015, 02:04     Наследование - вызов конструкторов и деструкторов #1
Делаю два класса - предок и потомок:
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
Первый и третий случаи - все понятно.
Подскажите пожалуйста, почему во втором случае не вызвался деструктор класса-наследника??
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
hoggy
5230 / 2121 / 404
Регистрация: 15.11.2014
Сообщений: 4,812
Завершенные тесты: 1
07.11.2015, 14:10     Наследование - вызов конструкторов и деструкторов #41
Цитата Сообщение от mporro Посмотреть сообщение
Чтобы корректно унаследоваться мне достаточно информации об открытом контракте, которая у меня уже есть.
Потому внедрение protected контракта -- это уже излишне. Зачем?
вы ж не от сферического вакуума наследуетесь.

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

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

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

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

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

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

В итоге: NVI не спасает от проблем наследования, но работа с открытыми виртуальными методами всегда более прозрачная.
hoggy
5230 / 2121 / 404
Регистрация: 15.11.2014
Сообщений: 4,812
Завершенные тесты: 1
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 - это тупо "фабричный метод".
наследники реализуют лишь мелкие не сильно значащие детальки.
а основняк крутится в базе,
и лишь время от времени тыркает наследников "уточнить мелочовку".

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

можно же сделать так, что и не придется.
это зависит от конкретных ситуаций,
и конкретных классов.
mporro
256 / 102 / 14
Регистрация: 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 Посмотреть сообщение
наследники реализуют лишь мелкие не сильно значащие детальки
Если речь только "о детальках реализации", то почему не стратегии Александреску?
Открытое наследование ещё и прицепит новый тип, по существу создаст новый контракт.
hoggy
5230 / 2121 / 404
Регистрация: 15.11.2014
Сообщений: 4,812
Завершенные тесты: 1
07.11.2015, 17:58     Наследование - вызов конструкторов и деструкторов #45
Цитата Сообщение от mporro Посмотреть сообщение
то почему не стратегии Александреску?
вы не особенно внимательный:
Цитата Сообщение от hoggy Посмотреть сообщение
можно ещё применить статическую стратегию на шаблонах.
пожалуй это будет эффективно.
но это уже тяжелая артиллерия.
шаблоно-магия не всегда приемлема.
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 18:10     Наследование - вызов конструкторов и деструкторов #46
Цитата Сообщение от hoggy Посмотреть сообщение
вы не особенно внимательный
Возможно.
Но и Вы на вопрос не ответили.
Ваш код под стратегии Александреску можно и без шаблонов переделать.
Почему не стратегии?
hoggy
5230 / 2121 / 404
Регистрация: 15.11.2014
Сообщений: 4,812
Завершенные тесты: 1
07.11.2015, 18:19     Наследование - вызов конструкторов и деструкторов #47
Цитата Сообщение от mporro Посмотреть сообщение
Ваш код под стратегии Александреску можно и без шаблонов переделать.
Почему не стратегии?
а зачем?
в отдельных ситуациях они - то, что доктор прописал.
но они более сложны в плане понимания и эксплуатации.

к тому же, они никак не избавят вас от ваших проблем с наследованием.
просто раньше вам приходилось втыкать в базовый класс.
а теперь - в класс стратегии.
те же яйца, только сбоку.
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 18:30     Наследование - вызов конструкторов и деструкторов #48
Цитата Сообщение от hoggy Посмотреть сообщение
просто раньше вам приходилось втыкать в базовый класс.
Со стратегиями мне уже действительно не приходится задумываться о "базовом классе", просто потому что у меня нет "базового класса". NVI подразумевает наследование и основного интерфейса, и интерфейса деталей реализации. То есть NVI вдвое сложнее.
hoggy
5230 / 2121 / 404
Регистрация: 15.11.2014
Сообщений: 4,812
Завершенные тесты: 1
07.11.2015, 18:35     Наследование - вызов конструкторов и деструкторов #49
Цитата Сообщение от mporro Посмотреть сообщение
Со стратегиями мне уже действительно не приходится задумываться о "базовом классе", просто потому что у меня нет "базового класса"
не факт.

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

что такое "интерфейс деталей реализации" мне не понятно.
однако сама фраза содержит внутреннее противоречие.
следует отделять понятие интерфейса от деталей реализации,
которые он инкапсулирует.
m45
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 22
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.
И опять - оба конструктора вызвались, а деструкторов вызвалось только один.
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
09.11.2015, 10:45     Наследование - вызов конструкторов и деструкторов #51
Поздравляю тебя, шарик. Всю первую страницу писали про виртуальные деструкторы, но ты так и не понял...
m45
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 22
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.
Ну что, эксперд нам расскажет как в этом примере вызываются виртуальные деструкторы????



Но, кажется, я и без экспертов понял в чем дело...
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
09.11.2015, 13:23     Наследование - вызов конструкторов и деструкторов #53
Цитата Сообщение от m45 Посмотреть сообщение
Но, кажется, я и без экспертов понял в чем дело...
Аллилуйя, ёп-т.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.11.2015, 19:07     Наследование - вызов конструкторов и деструкторов
Еще ссылки по теме:

C++ Вызов конструкторов/деструкторов при наследовании
Классы и обьекты в С++. Выполнить исследование вызовов конструкторов и деструкторов C++
Задание с использованием конструкторов и деструкторов C++

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

Или воспользуйтесь поиском по форуму:
m45
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 22
09.11.2015, 19:07  [ТС]     Наследование - вызов конструкторов и деструкторов #54
Цитата Сообщение от castaway Посмотреть сообщение
Аллилуйя, ёп-т.
Аминь, чо.
Yandex
Объявления
09.11.2015, 19:07     Наследование - вызов конструкторов и деструкторов
Ответ Создать тему
Опции темы

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