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

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

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

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

01.11.2015, 02:04. Просмотров 1023. Ответов 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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.11.2015, 02:04
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Наследование - вызов конструкторов и деструкторов (C++):

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

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

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

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

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

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

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
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 если и не является "анти-паттерном", то очень близко к этому.
1
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
Ну как я мог её не заметить?! Долго ведь искал… Спасибо

0
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
05.11.2015, 13:17 #18
Цитата Сообщение от gromo Посмотреть сообщение
Наоборот, скрывается та деталь, что функция может менять свою реализацию
Эта "деталь" никуда не скрывается. Она "перемещается". Более того! Создаётся новая деталь и более тесная связь.
Если с "виртуальным" интерфейсом наследнику нужно было знать только контракты открытых методов, то теперь к ним ещё прилипнут контракты приватных методов.
Всё это просто иллюзия. В том-то и проблема.
0
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
И это замечательно
1
Fallenworld
76 / 76 / 9
Регистрация: 14.04.2014
Сообщений: 408
05.11.2015, 13:49 #20
Цитата Сообщение от mporro Посмотреть сообщение
наследнику нужно было знать только контракты открытых методов
в том то и суть, что при nvi наследник не знает открытых методов. А закрытые определяет из своих потребностей.
0
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.
0
Ilot
Модератор
Эксперт С++
1811 / 1168 / 229
Регистрация: 16.05.2013
Сообщений: 3,082
Записей в блоге: 5
Завершенные тесты: 1
05.11.2015, 14:55 #22
Цитата Сообщение от m45 Посмотреть сообщение
Так а почему для конструктора не нужно указывать метод виртуальным?
Потому, что пока не построен объект для него не существует таблицы виртуальных функций. Нельзя выбрать тип конструктора не имея объекта от имени которого эта функция будет вызывается. Виртуальные деструкторы конечно отличаются от простых методов однако ж они вызываются для уже существующих объектов.
0
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
05.11.2015, 14:59 #23
mporro, метода private_hello не может не быть, ибо он объявлен в самом базовом классе.
И почему у вас в Derived переопределение чисто виртуальной функции в чисто виртуальную?!
0
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 много ограничений и недостатков, а преимуществ очень мало.
Их следует использовать только в специфических ситуациях, но никак не с такими претензиями, как рекламировал Саттер.
0
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
05.11.2015, 15:51 #25
mporro, так ведь невиртуальный метод hello, как раз и предназначен, чтобы скрыть это. В нем проверяем все предусловия, инварианты и постусловия. Если на то пошло, то можно в самом базовом классе сделать безобидную заглушку для impl-метода (например, сделать его пустым), которая избавит вас от необходимости делать его пустым в своем подклассе, тобишь "вдаваться в детали".
0
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 говорит что-то про отношение является между реализацией, которая использует методы и реализацией, которая эти методы поставляет.
0
hoggy
Нарушитель
6564 / 2745 / 474
Регистрация: 15.11.2014
Сообщений: 6,087
Завершенные тесты: 1
07.11.2015, 11:35 #27
Цитата Сообщение от mporro Посмотреть сообщение
то теперь к ним ещё прилипнут контракты приватных методов.
противоречие здравому смыслу,
и самой причине существования модификатора доступа private

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

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

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

и кстати, у вас там выше собственность предназначенная для наследников помечена как private
а должна быть protected.
косяк в дизайне и печалька.
0
gromo
370 / 269 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
07.11.2015, 12:06 #30
Цитата Сообщение от hoggy Посмотреть сообщение
у вас там выше собственность предназначенная для наследников помечена как private
а должна быть protected.
Где именно ?
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.11.2015, 12:06
Привет! Вот еще темы с ответами:

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

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

Оценить правильность использования конструкторов, деструкторов в коде - C++
Всем доброго времени суток. Не могли бы вы оценить правильность использования конструкторов,деструкторов и динамического выделения памяти...

Классы и обьекты в С++. Выполнить исследование вызовов конструкторов и деструкторов - C++
Написать программу, в которой создаются и разрушаются обьекты, определенного пользователем класса. Выполнить исследование вызовов...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
07.11.2015, 12:06
Ответ Создать тему
Опции темы

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