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

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

01.11.2015, 02:04. Показов 5862. Ответов 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
Первый и третий случаи - все понятно.
Подскажите пожалуйста, почему во втором случае не вызвался деструктор класса-наследника??
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.11.2015, 02:04
Ответы с готовыми решениями:

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

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

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

53
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 14:38
Студворк — интернет-сервис помощи студентам
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.
0
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2226 / 1428 / 420
Регистрация: 16.05.2013
Сообщений: 3,651
Записей в блоге: 6
05.11.2015, 14:55
Цитата Сообщение от m45 Посмотреть сообщение
Так а почему для конструктора не нужно указывать метод виртуальным?
Потому, что пока не построен объект для него не существует таблицы виртуальных функций. Нельзя выбрать тип конструктора не имея объекта от имени которого эта функция будет вызывается. Виртуальные деструкторы конечно отличаются от простых методов однако ж они вызываются для уже существующих объектов.
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
05.11.2015, 14:59
mporro, метода private_hello не может не быть, ибо он объявлен в самом базовом классе.
И почему у вас в Derived переопределение чисто виртуальной функции в чисто виртуальную?!
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 15:32
gromo
Цитата Сообщение от gromo Посмотреть сообщение
ибо он объявлен в самом базовом классе
Ммм... А почему же его нет? Он есть. В том классе, который создаётся, метод вполне определён.

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

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

Добавлено через 29 минут
P.S.
Я не спорю, что в определённых ситуациях нечто подобное может потребоваться. Может.
Но! У non-virtual interfaces много ограничений и недостатков, а преимуществ очень мало.
Их следует использовать только в специфических ситуациях, но никак не с такими претензиями, как рекламировал Саттер.
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
05.11.2015, 15:51
mporro, так ведь невиртуальный метод hello, как раз и предназначен, чтобы скрыть это. В нем проверяем все предусловия, инварианты и постусловия. Если на то пошло, то можно в самом базовом классе сделать безобидную заглушку для impl-метода (например, сделать его пустым), которая избавит вас от необходимости делать его пустым в своем подклассе, тобишь "вдаваться в детали".
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 17:06
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 говорит что-то про отношение является между реализацией, которая использует методы и реализацией, которая эти методы поставляет.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 11:35
Цитата Сообщение от mporro Посмотреть сообщение
то теперь к ним ещё прилипнут контракты приватных методов.
противоречие здравому смыслу,
и самой причине существования модификатора доступа private

Добавлено через 1 минуту
Цитата Сообщение от mporro Посмотреть сообщение
и ещё на приватные методы смотреть.
не нужно.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 11:47
Цитата Сообщение от hoggy Посмотреть сообщение
не нужно.
Как обычно, только в Ваших фантазиях.
Обсуждать их не имеет смысла.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 11:52
Цитата Сообщение от mporro Посмотреть сообщение
Как обычно, только в Ваших фантазиях.
вам часто приходится втыкать в приватные секции библиотечных классов?
скорее всего вы даже не подозреваете об их существовании.
но это не мешает вам продуктивно с ними работать.

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

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

и кстати, у вас там выше собственность предназначенная для наследников помечена как private
а должна быть protected.
косяк в дизайне и печалька.
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
07.11.2015, 12:06
Цитата Сообщение от hoggy Посмотреть сообщение
у вас там выше собственность предназначенная для наследников помечена как private
а должна быть protected.
Где именно ?
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 12:22
Цитата Сообщение от hoggy Посмотреть сообщение
так и должно быть с грамотно сконструированным кодом.
Прочитайте статью Саттера.
Там чёрным по белому написано keep virtual functions private.
Вся суть NVI в том, что Вы перегружаете не открытый контракт, а закрытый.
А вот чтобы перегружать закрытый контракт, Вам придётся в него "втыкать".
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 12:47
Цитата Сообщение от gromo Посмотреть сообщение
Где именно ?
Цитата Сообщение от mporro Посмотреть сообщение
private:
* * virtual void private_hello(std::ostream&) =0;
частная собственность класса наследников не должна касаться.
имя функции-члена тоже доставляет:
"переопределяйте детали реализации"
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
07.11.2015, 12:49
Цитата Сообщение от hoggy Посмотреть сообщение
имя функции-члена тоже доставляет:
"переопределяйте детали реализации"
Прочитайте стать Virtuality Саттера.

Почти вся стандартная библиотека построена на этой идиоме.

Еще часто применяют префикс `do_`. Публичная интерфейсная функция request(), рабочая функция — do_request(), что я нахожу более привлекательным нежели `private_`, но кому как нравится
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 12:51
hoggy
Сначала, пожалуйста, ознакомьтесь со статьёй Саттера.
Только после этого отвечайте по теме NVI.
Вопросы, которые Вы пытаетесь адресовать мне, следует адресовать Саттеру.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 13:02
Цитата Сообщение от mporro Посмотреть сообщение
Там чёрным по белому написано keep virtual functions private.
это может быть нужно только и только,
если существует объективная причина не позволить наследнику
выполнить прямой вызов виртуальной функции базового класса,

хотя на вскидку, мне трудно представить зачем такое может понадобиться.

во всем остальном приватные виртуальные функции-члены не дают никаких преимуществ,
по сравнению с protected

только с толку сбивают.
потому что protected - это то, что доктор прописал специально для наследников.
а private - частная собственность.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 13:04
hoggy
Мне то зачем это рассказывать?
Расскажите это Саттеру.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 13:21
Цитата Сообщение от mporro Посмотреть сообщение
Мне то зачем это рассказывать?
Расскажите это Саттеру.
мне просто стало любопытно:
вы приводите в качестве аргумента некий авторитет: Саттера.
но понимаете ли вы его?
или вы бездумно верите авторитетам?

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

я читал Саттера если что.
и мне нет смысла ему что-то рассказывать.

потому что подобный тезис:
Guideline #2: Prefer to make virtual functions private.
That's easy. This lets the derived classes override the function to customize the behavior as needed, without further exposing the virtual functions directly by making them callable by derived classes (as would be possible if the functions were just protected). The point is that virtual functions exist to allow customization; unless they also need to be invoked directly from within derived classes' code, there's no need to ever make them anything but private. But sometimes we do need to invoke the base versions of virtual functions (see the article "Virtually Yours"[5] for an example), and in that case only it makes sense to make those virtual functions protected, thus:

(ц)Саттер.
практически целиком и полностью совпадает с моим собственным (см #35).

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

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

что на мой взгляд ухудшает читабельность,
и не несет профита.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 13:25
hoggy
Тогда мой Вам ответ состоит в том, что втыкать придётся не только в открытый контракт, который случайно может быть нарушен наследником, но ещё в защищённый (protected) контракт, который тоже нужно соблюдать.
Зачем мне нужна эта лишняя деталь защищённого контракта?

Замена private на protected не решает проблемы лишней детали.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.11.2015, 13:36
Цитата Сообщение от mporro Посмотреть сообщение
втыкать придётся не только в открытый контракт
только прототип.
реализация его не интересует.

Цитата Сообщение от mporro Посмотреть сообщение
в защищённый (protected) контракт, который тоже нужно соблюдать.
разумеется. он для того и существует,
что бы разработчик наследника в него втыкал,
и соблюдал.
Цитата Сообщение от mporro Посмотреть сообщение
Зачем мне нужна эта лишняя деталь защищённого контракта?
странный вопрос.
что бы корректно унаследоваться и породить наследника.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
07.11.2015, 13:56
Цитата Сообщение от hoggy Посмотреть сообщение
что бы корректно унаследоваться и породить наследника
Чтобы корректно унаследоваться мне достаточно информации об открытом контракте, которая у меня уже есть.
Потому внедрение protected контракта -- это уже излишне. Зачем?

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

Кроме того, меня по-прежнему будут волновать аксиомы интерфейса. Я вполне могу написать в Derived классе свой метод hello, который будет успешно работать для подалгебры Derived и не удовлетворять аксиомам Base, если не буду знать аксиом Base. То есть, NVI не может меня избавить от необходимости подробно втыкать в открытый интерфейс.

Итог: вместо того, чтобы втыкать только в открытый интерфейс, как с обычным наследованием, я должен ещё и разобрать защищённый.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.11.2015, 13:56

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Теория всего 12. ВГК
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики 1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928 Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
Теория всего 10. Клод трусишка
anaschu 21.07.2026
Алгоритмический суицид ИИ: Когда математика ОДУ взламывает цензурные шлюзы Свежайший мета-прецедент нашей разработки! Клод официально отказался строить итоговую кроссплатформенную модель, как. . .
Теория всего 9. Окончательная проработка метафоры "дерево = традиции"
anaschu 21.07.2026
Скрытые параметры ядра ОДУ: Механика Глубинного Рока Клод утаил от вас ключевую математику кризисов. В движке игры зашиты пять скрытых коэффициентов, определяющих, как именно ТНК и Мемы ломают. . .
Теория всего 8. Clauude трусишка. Ответ джемени
anaschu 21.07.2026
Игровой баланс «Модели Всего»: Алгоритмический блок как механика Семантического БуфераЭтот скриншот отказа Клода — идеальный, чистейший прецедент для нашей Теории Всего. Вы столкнулись не просто с. . .
Теория всего 7. Дерево - это патриархат, грибы - это феминизм
anaschu 21.07.2026
Уничтожение Патриархата: Как ТНК, Мемы и Половой отбор зачистили «Сексуальный Пролетариат» Величайшая иллюзия современного человека — вера в «свободу воли», «социальный прогресс» и «эволюцию. . .
История и социология Терры на примере борьбы микориз за пространство. 1. Глоссарий терры.
anaschu 21.07.2026
Решил тут подумать о возможности сделать лор некоторой комп игры - стратегии, или худжественной книги антиутопии, которые будут юзать планету,которая максимально будет похожа на нашу землю, но где. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru