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

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

Войти
Регистрация
Восстановить пароль
 
 
m45
0 / 0 / 0
Регистрация: 06.07.2015
Сообщений: 24
#1

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

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

Делаю два класса - предок и потомок:
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
Первый и третий случаи - все понятно.
Подскажите пожалуйста, почему во втором случае не вызвался деструктор класса-наследника??
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.11.2015, 02:04     Наследование - вызов конструкторов и деструкторов
Посмотрите здесь:
C++ Вызов конструкторов/деструкторов при наследовании
C++ Вызов лишних конструкторов и деструкторов в std::vector
C++ Порядок вызова конструкторов/деструкторов
Задание с использованием конструкторов и деструкторов C++
C++ Правильное использование конструкторов и деструкторов
C++ Как реализовать набор конструкторов и деструкторов
Ошибки в программе с использованием конструкторов/деструкторов C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 12:51     Наследование - вызов конструкторов и деструкторов #16
gromo
Ничего разделить не получится.
Как бы Вы ни пытались, но
C++
1
2
class A_impl: public B_type {
};
всегда вместе с типовой меткой прицепит к A_impl реализацию из B_type. Единственное, что можно сделать, это лишить B_type всякой реализации, в том числе и разного рода приватных методов (это же детали реализации, зачем они там, где реализации нет?)

Приличный дизайн подразумевал бы нечто подобное:

-- определим тип
Type Show {
show(some_stream: Tostream): Tostream
}


Object SomeImplementation Ensures Show {
Show::show(some_stream: Tostream): Tostream
{
-- code goes here
}
}

-- ошибка компиляции SomeImplementation не определяет тип
Object TheOtherImplementation Ensures SomeImplementation {
}

То есть, типы и реализации принципиально разделены.

Non-virtual interfaces -- это просто внедрение лишней детали. А лучшая деталь та, которой нет.
По-существу non-virtual interface если и не является "анти-паттерном", то очень близко к этому.
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
05.11.2015, 13:10     Наследование - вызов конструкторов и деструкторов #17
Цитата Сообщение от mporro Посмотреть сообщение
всегда вместе с типовой меткой прицепит к A_impl реализацию из B_type.
Можно в B_type сделать функции чисто виртуальными и никакого прицепления не будет. Вы это имели ввиду здесь:
Цитата Сообщение от mporro Посмотреть сообщение
Единственное, что можно сделать, это лишить B_type всякой реализации,
?
Цитата Сообщение от mporro Посмотреть сообщение
Non-virtual interfaces -- это просто внедрение лишней детали. А лучшая деталь та, которой нет.
Какой еще детали? Наоборот, скрывается та деталь, что функция может менять свою реализацию в производных классах. Вы статью Virtuality по ссылке выше читали?

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от gru74ik Посмотреть сообщение
Внезапно: кнопочкой inline
Ну как я мог её не заметить?! Долго ведь искал… Спасибо

mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 13:17     Наследование - вызов конструкторов и деструкторов #18
Цитата Сообщение от gromo Посмотреть сообщение
Наоборот, скрывается та деталь, что функция может менять свою реализацию
Эта "деталь" никуда не скрывается. Она "перемещается". Более того! Создаётся новая деталь и более тесная связь.
Если с "виртуальным" интерфейсом наследнику нужно было знать только контракты открытых методов, то теперь к ним ещё прилипнут контракты приватных методов.
Всё это просто иллюзия. В том-то и проблема.
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
05.11.2015, 13:47     Наследование - вызов конструкторов и деструкторов #19
mporro, действительно, рассуждать можно с разных позиций и все они в чем-то правильны и в чем-то неправильны. Здесь, на мой взгляд, хорошо впишется цитата:
There are just two kinds of languages: the ones everybody complains about and the ones nobody uses. — Bjarne Stroustrup
И это замечательно
Fallenworld
76 / 76 / 9
Регистрация: 14.04.2014
Сообщений: 408
05.11.2015, 13:49     Наследование - вызов конструкторов и деструкторов #20
Цитата Сообщение от mporro Посмотреть сообщение
наследнику нужно было знать только контракты открытых методов
в том то и суть, что при nvi наследник не знает открытых методов. А закрытые определяет из своих потребностей.
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 14:38     Наследование - вызов конструкторов и деструкторов #21
Fallenworld
Цитата Сообщение от Fallenworld Посмотреть сообщение
наследник не знает открытых методов
Кто угодно знает контракты открытых методов, а не только наследник.
Вот только у наследника больше обязанностей, так как класс предок ещё и супертип.
Приходится и LSP соблюдать, если создаём методы с той же сигнатурой, и ещё на приватные методы смотреть.

Добавлено через 4 минуты
gromo
Я не говорю, что не следует использовать C++... Но пытаться извернуться и исправить ошибки дизайна хаками -- не самый хороший путь.
Что есть, то и используем. Более разумным кажется определять типы чисто-виртуальными функциями. Гораздо меньше проблем.

Добавлено через 17 минут
* * *
Пример, что мы не можем полностью игнорировать то, как устроены "невиртуальные" методы базового класса.
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
class Base {
public:
    std::ostream& hello(std::ostream& stream)
    {
        private_hello(stream);
        return stream;
    }
    
private:
    virtual void private_hello(std::ostream&) =0;
};
 
class Derived: public Base {
public:
    Derived(std::ostream& stream)
    {
        Base::hello(stream);
    }
    
private:
    virtual void private_hello(std::ostream&) =0;
};
 
class NextDerived: public Derived {
public:
    NextDerived(std::ostream& stream): Derived(stream) { }
 
private:
    void private_hello(std::ostream& stream)
    {
        stream << "Hello NextDerived" << std::endl;
    }
};
Нам, оказывается, крайне важно знать, что метод hello нельзя вызвать, если нет метода private_hello.
Ilot
Модератор
Эксперт С++
1807 / 1164 / 226
Регистрация: 16.05.2013
Сообщений: 3,060
Записей в блоге: 5
Завершенные тесты: 1
05.11.2015, 14:55     Наследование - вызов конструкторов и деструкторов #22
Цитата Сообщение от m45 Посмотреть сообщение
Так а почему для конструктора не нужно указывать метод виртуальным?
Потому, что пока не построен объект для него не существует таблицы виртуальных функций. Нельзя выбрать тип конструктора не имея объекта от имени которого эта функция будет вызывается. Виртуальные деструкторы конечно отличаются от простых методов однако ж они вызываются для уже существующих объектов.
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
05.11.2015, 14:59     Наследование - вызов конструкторов и деструкторов #23
mporro, метода private_hello не может не быть, ибо он объявлен в самом базовом классе.
И почему у вас в Derived переопределение чисто виртуальной функции в чисто виртуальную?!
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 15:32     Наследование - вызов конструкторов и деструкторов #24
gromo
Цитата Сообщение от gromo Посмотреть сообщение
ибо он объявлен в самом базовом классе
Ммм... А почему же его нет? Он есть. В том классе, который создаётся, метод вполне определён.

Цитата Сообщение от gromo Посмотреть сообщение
И почему у вас в Derived переопределение чисто виртуальной функции в чисто виртуальную?!
Для наглядности. Можно вырезать это определение -- ничего не изменится.

The bottom line is: нам необходимо знать, что метод Base::hello нельзя использовать, если не определён метод private_hello, нам необходимо знать детали реализации невиртуальных методов. А если бы мы сразу использовали чисто-виртуальный метод Base::hello, то подобных проблем у нас бы не возникло.

Добавлено через 29 минут
P.S.
Я не спорю, что в определённых ситуациях нечто подобное может потребоваться. Может.
Но! У non-virtual interfaces много ограничений и недостатков, а преимуществ очень мало.
Их следует использовать только в специфических ситуациях, но никак не с такими претензиями, как рекламировал Саттер.
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
05.11.2015, 15:51     Наследование - вызов конструкторов и деструкторов #25
mporro, так ведь невиртуальный метод hello, как раз и предназначен, чтобы скрыть это. В нем проверяем все предусловия, инварианты и постусловия. Если на то пошло, то можно в самом базовом классе сделать безобидную заглушку для impl-метода (например, сделать его пустым), которая избавит вас от необходимости делать его пустым в своем подклассе, тобишь "вдаваться в детали".
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 17:06     Наследование - вызов конструкторов и деструкторов #26
gromo
Цитата Сообщение от gromo Посмотреть сообщение
как раз и предназначен, чтобы скрыть это
Он ничего не скрывает. В лучшем случае можно говорить о том, что базовый интерфейс диктует стратегию.

То, что я вижу, и почему больше не пишу ничего подобного, это пародия на следующий паттерн:
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
struct TSmallMethods {
public:
   virtual method_A =0;
   virtual method_B =0;
   virtual method_C =0; 
};
 
class StrategicallyPlacedMethods {
public:
    spm_method_A {
        small_methods_provider.method_A;
        small_methods_provider.method_B;
    }
 
    spm_method_B {
        small_methods_provider.method_A;
        small_methods_provider.method_C;
        small_methods_provider.method_B;
    }
 
    StrategicallyPlacedMethods(TSmallMethods& small_methods_provider);
 
private:
    TSmallMethods& small_methods_provider;
};
Только вместо того, чтобы ясно указать "я использую такие-то методы", NVI говорит что-то про отношение является между реализацией, которая использует методы и реализацией, которая эти методы поставляет.
hoggy
6431 / 2649 / 460
Регистрация: 15.11.2014
Сообщений: 5,838
Завершенные тесты: 1
07.11.2015, 11:35     Наследование - вызов конструкторов и деструкторов #27
Цитата Сообщение от mporro Посмотреть сообщение
то теперь к ним ещё прилипнут контракты приватных методов.
противоречие здравому смыслу,
и самой причине существования модификатора доступа private

Добавлено через 1 минуту
Цитата Сообщение от mporro Посмотреть сообщение
и ещё на приватные методы смотреть.
не нужно.
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 11:47     Наследование - вызов конструкторов и деструкторов #28
Цитата Сообщение от hoggy Посмотреть сообщение
не нужно.
Как обычно, только в Ваших фантазиях.
Обсуждать их не имеет смысла.
hoggy
6431 / 2649 / 460
Регистрация: 15.11.2014
Сообщений: 5,838
Завершенные тесты: 1
07.11.2015, 11:52     Наследование - вызов конструкторов и деструкторов #29
Цитата Сообщение от mporro Посмотреть сообщение
Как обычно, только в Ваших фантазиях.
вам часто приходится втыкать в приватные секции библиотечных классов?
скорее всего вы даже не подозреваете об их существовании.
но это не мешает вам продуктивно с ними работать.

так и должно быть с грамотно сконструированным кодом.

необходимость лазить в приваты - последствия вашего личного не совершенства
в этом ужассном и реальном мире.

и кстати, у вас там выше собственность предназначенная для наследников помечена как private
а должна быть protected.
косяк в дизайне и печалька.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.11.2015, 12:06     Наследование - вызов конструкторов и деструкторов
Еще ссылки по теме:
Разработка классов, создание конструкторов и деструкторов C++
C++ Оценить правильность использования конструкторов, деструкторов в коде
Классы и обьекты в С++. Выполнить исследование вызовов конструкторов и деструкторов C++
C++ Простая прога на использование конструкторов и деструкторов в с++ не работает ( не пойму почему (
C++ Создание и разрушение объектов класса, исследование вызовов конструкторов и деструкторов

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

Или воспользуйтесь поиском по форуму:
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
07.11.2015, 12:06     Наследование - вызов конструкторов и деструкторов #30
Цитата Сообщение от hoggy Посмотреть сообщение
у вас там выше собственность предназначенная для наследников помечена как private
а должна быть protected.
Где именно ?
Yandex
Объявления
07.11.2015, 12:06     Наследование - вызов конструкторов и деструкторов
Ответ Создать тему
Опции темы

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