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

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 55, средняя оценка - 4.93
rar14
28 / 22 / 1
Регистрация: 14.04.2009
Сообщений: 448
#1

Наследуются ли конструкторы и деструкторы? - C++

02.06.2009, 14:54. Просмотров 7683. Ответов 124
Метки нет (Все метки)

При наследовании происходит ли наследование конструкторов и деструкторов базового класса?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.06.2009, 14:54
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Наследуются ли конструкторы и деструкторы? (C++):

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

Почему не наследуются конструкторы? - C++
Здравствуйте. Гугл говорит, что конструкторы в C++ унаследовать никак нельзя. Почему так? В чём проблема с их наследованием? Хотел...

Конструкторы и деструкторы - C++
Помогите, пожалуйста, исправить программу и закончить ее как надо. Необходимо реализовать класс с двумя полями, имеющими имена first и...

Конструкторы и деструкторы - C++
Здравствуйте уважаемые программисты, помогите пожалуйста новичку? Не могу разобраться в программе, где смог там написал комментарий и то не...

Конструкторы и деструкторы - C++
Не понимаю, как закончить программу. Написала конструктор и деструктор, хотя он тут и не нужен по идее. Но по заданию сделала. А как...

Конструкторы и деструкторы - C++
Необходимо реализовать класс с двумя полями, имеющими имена first и second. Обязательно должны присутствовать: Для инициализации...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
kzru_hunter
1090 / 765 / 58
Регистрация: 01.02.2011
Сообщений: 1,779
Записей в блоге: 1
13.01.2016, 18:30 #31
Цитата Сообщение от xecu91 Посмотреть сообщение
Исчерпывающее объяснение здесь.
Я там не увидел объяснения. Где именно? Я там только увидел ошибку в том, что ему нужно явно вызывать конструктор базового класса в конструкторе производного класса.
0
Croessmah
Эксперт CЭксперт С++
13228 / 7500 / 845
Регистрация: 27.09.2012
Сообщений: 18,419
Записей в блоге: 3
Завершенные тесты: 1
13.01.2016, 18:42 #32
Цитата Сообщение от kzru_hunter Посмотреть сообщение
// этот конструктор можно вызвать, несмотря на то, что так нельзя делать
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
#include <iostream>
 
class A
{
public:
 
};
 
class B : public A
{
public:
    void func()
    {
       A::A(); // этот конструктор можно вызвать, несмотря на то, что так нельзя делать
       //C::C(); этот конструктор нельзя вызвать
    }
};
 
class C : public A
{
public:
    
};
 
int main()
{
    std::cout << "Hello, world!\n";
}
http://rextester.com/KKWLK56056
0
xecu91
3 / 3 / 0
Регистрация: 09.01.2012
Сообщений: 28
13.01.2016, 18:44 #33
Для начала нужно понять, о каком конструкторе идёт речь.

Компилятор может генерировать конструкторы автоматически, например, конструктор по умолчанию. Если он генерирует конструктор по умолчанию для производного класса, то он сам вставит вызов конструктора базового класса. Это можно легко увидеть, выполнив такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
class A {
 public:
    A() {
        std::cout << "A::A()\n";
    }
};
 
class B : public A {
};
 
int main() {
    B b;
    return 0;
}
Если же речь идёт о конструкторе, который не генерируется компилятором автоматически, то вызов конструкторов базового класса - ответственность программиста. Например, следующий код не будет скомпилирован:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
class A {
 public:
    explicit A(int v) {
        std::cout << "A::A(" << v << ")\n";
    }
};
 
class B : public A {
};
 
int main() {
    B b(2);
    return 0;
}
Это и означает, что конструкторы не наследуются. Однако, для достижения некоторого "наследования" конструкторов есть два способа. Первый, соответствующий стандарту C++03:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
class A {
 public:
    explicit A(int v) {
        std::cout << "A::A(" << v << ")\n";
    }
};
 
class B : public A {
 public:
    B(int v) : A(v) {
    }
};
 
int main() {
    B b(2);
    return 0;
}
Здесь мы явно вызываем конструктор базового класса в списке инициализации производного класса.

Второй способ, который соответствует стандарту C++11:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
class A {
 public:
    explicit A(int v) {
        std::cout << "A::A(" << v << ")\n";
    }
};
 
class B : public A {
 public:
    using A::A;
};
 
int main() {
    B b(2);
    return 0;
}
Здесь мы явно говорим, что необходимо унаследовать конструкторы базового класса A.
0
kzru_hunter
1090 / 765 / 58
Регистрация: 01.02.2011
Сообщений: 1,779
Записей в блоге: 1
13.01.2016, 19:20 #34
Цитата Сообщение от Croessmah Посмотреть сообщение
http://rextester.com/KKWLK56056
Да, странно как-то это. Но в Visual Studio 2013 без ошибок компилируется (появляется только ошибка intellisense).
C++ Builder 6 не хочет компилить, багнутый, левую ошибку показывает. Но начинает компилить только, когда вручную определяешь конструктор по умолчанию A::A().

xecu91
То что у тебя вначале написано - это не из-за наследования. У каждого класса должны быть свои конструкторы. Если ни один не определён, то генерируется конструктор по умолчанию, в код которого добавляется неявный вызов конструктора по умолчанию базового класса. Но для конструктора по умолчания базового класса стоит модификатор explicit, который требует чтобы его вызывали явно. Поэтому и ошибка. И никак не из-за наследования.

А то что в C++11 добавили так называемый constructor inheritance, то я бы эту возможность назвал так - constructor adoption (заимствование конструктора). И у меня почему-то код не компилится в VS 2013 (вместо конструктора A::A пытается вызвать копирующий конструктор B:B(const B&), но не может т.к. не может преобразовать int в B), хотя rextester компилит.
0
Mr.X
Эксперт С++
3049 / 1694 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
13.01.2016, 20:15 #35
М-да, веселый язык С++! О каких бы самых базовых вещах ни зашла речь, внезапно выясняется, что никто о них не имеет адекватного представления!
0
hoggy
Нарушитель
6589 / 2770 / 476
Регистрация: 15.11.2014
Сообщений: 6,122
Завершенные тесты: 1
13.01.2016, 20:45 #36
Цитата Сообщение от CheshireCat Посмотреть сообщение
Неверно. Конструкторы и деструкторы не наследуются.
наследуются.
не только конструкторы - весь класс,
со всем своим барахлом.

весь функционал, и все данные.
0
xecu91
3 / 3 / 0
Регистрация: 09.01.2012
Сообщений: 28
13.01.2016, 21:25 #37
kzru_hunter, это не так, попробуй убери оттуда explicit и скомпилируй.
0
rikimaru2013
C++ Game Dev
2436 / 1130 / 240
Регистрация: 30.11.2013
Сообщений: 3,687
13.01.2016, 21:48 #38
Смотря у кого спрашивают:
- если у мидла: наследник наследует все методы и свойства родителя.
- если у джуна: то не наследуются (конструктор, деструктор, оператор присваения и friend отношения)
0
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
14.01.2016, 01:05 #39
Цитата Сообщение от kzru_hunter Посмотреть сообщение
Так наследуются или нет?
Нет, не наследуются.
Они могут генерироваться компилятором, но не наследуются.
0
kzru_hunter
1090 / 765 / 58
Регистрация: 01.02.2011
Сообщений: 1,779
Записей в блоге: 1
14.01.2016, 07:39 #40
Цитата Сообщение от xecu91 Посмотреть сообщение
это не так, попробуй убери оттуда explicit и скомпилируй.
Да, я там поторопился. Не обратил внимания на то, что там не был определен конструктор по умолчанию. И ошибся насчет explicit: генерируемый по умолчанию конструктор производного класса все-таки может неявно вызвать explicit конструктор по умолчанию базового класса.

Цитата Сообщение от xecu91 Посмотреть сообщение
Если же речь идёт о конструкторе, который не генерируется компилятором автоматически, то вызов конструкторов базового класса - ответственность программиста. Например, следующий код не будет скомпилирован:
....
Это и означает, что конструкторы не наследуются.
В том то и проблема, что я не вижу между этими заключениями никакой связи. Я вижу только то, что в том коде был вручную пользователем определен кастомный конструктор в базовом классе, из-за чего компилятор не сгенерировал конструктор по умолчанию для этого базового класса. Поэтому компилятор и не может сгенерировать конструктор по умолчанию для производного класса, т.к. ему для этого нужен конструктор по умолчания базового класса, а он в свою очередь не был сгененерирован из-за причин, описанных выше. К сожалению, для меня это не означает, что конструкторы не наследуются. Как у вас получилось прийти к такому выводу - я не понимаю.

Цитата Сообщение от mporro Посмотреть сообщение
Они могут генерироваться компилятором, но не наследуются.
почему не наследуются?

Раз Страуструп говорит, что не наследуются, значит скорее всего так и есть.
Но как я говорил, мне не даёт покоя следующее:
C++
1
2
3
4
5
6
7
8
B b;
B h;    
b.A::operator=(h); // можно вызвать оператор присваивания базового класса
 
// можно ещё использовать в производном классе using A::operator=
// и тогда можно просто использовать b = h; <- вызовется A::operator=
 
B *j = (B*)(new B::A()); // можно вызвать конструктор базового класса, но при этом будет создан объект базового класса, а не производного
Может дело в том, как понимать и видеть значение понятия наследования? Пытаюсь увидеть так, как видит Страуструп или Прата, но не получается.
0
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
14.01.2016, 09:14 #41
kzru_hunter
В С++ наследование делает одновременно два дела: подтип наследует типовую метку супертипа и устанавливает между выведенным классом и базовым классом отношение композиции. Словно бы в В Вы определили поле типа A и разместили там какой-то объект. Это приводит к ужасающей путанице между наследованием и композицией. В частности, C++ позволяет "унаследовать" класс закрытым образом! Это приводит к тому, что два класса входят в отношение композиции, но не в ходят в отношение наследования вообще, а называется эта операция "закрытым наследованием". Также и с конструкторами: они не наследуются, наследовать их было бы крайне глупо, но они агрегируются.

Добавлено через 14 минут
kzru_hunter
Есть ещё такой терминологический изыск: наследование интерфейса и наследование реализации. В этом смысле можно говорить, что интерфейс базовых конструкторов не наследуется, а реализация -- да.

Можно развести дискуссию и на такую тему, что обсуждение наследования конструктора бессмысленно, как деление ноль, так как нельзя сказать, что объект обрабатывает сообщение о своём конструировании, ведь он вообще не создан!
0
hoggy
Нарушитель
6589 / 2770 / 476
Регистрация: 15.11.2014
Сообщений: 6,122
Завершенные тесты: 1
14.01.2016, 09:53 #42
Цитата Сообщение от kzru_hunter Посмотреть сообщение
В том то и проблема, что я не вижу между этими заключениями никакой связи.
потому что её там нет.
товарищ несет пургу.

Добавлено через 24 минуты
Цитата Сообщение от kzru_hunter Посмотреть сообщение
Может дело в том, как понимать и видеть значение понятия наследования?
возможно одно и только одно понимание, которое не будет противоречить самому себе:
класс А унаследовал от класса Б все

получаем некий Д, который представляет собой плоскую модель [A:Б]
то бишь все от А, и все от Б.

доказательство непротиворечивости:

люди грамотные, и балбесы сходяццо в одном:
наследуются фукнкции-члены, и члены-данные классов.

в частности мы можем позвать функцию член Б, через имя класса А:

C++
1
2
3
4
5
int main(){
    struct B { void foo(){} };
    struct A: B {};
    A a a.foo();
}
теперь вносим функцию-член в приваты:

C++
1
2
3
4
5
int main(){
    class B { void foo(){} };
    struct A: B {};
    A a a.foo(); // error: private
}
внимание вопрос: наследуется ли функция-член foo?
если балбес скажет: нет,
тогда он и начнет противоречить самому себе.

функция-член наследуется.
она просто не доступна в контексте класса наследника.

технически, наследование - это тупо объединение двух (или более) классов в один.

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

C++
1
2
3
4
5
6
// данная модель иллюстрирует принцип наследования
template<class T> struct derrived: T {};
struct base {};
 
typedef derrived<base>
    agregat;
агрегат - продукт синтеза (наследования).
плоская модель, которая обладает всем функционалом обоих классов
но при этом не является ни derrived, ни base


все что нужно понять балбесам,
коих в этой теме как минимум несколько:
вопрос не в том, наследуется ли (да, наследуется).
вопрос: а доступен ли?

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

но не техническими ограничениями.

с технической точки зрения любой функционал базового класса,
будь то функция-член, или конструктор
(который, с технической точки зрения так же является функцией)
реально существует.
0
Mr.X
Эксперт С++
3049 / 1694 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
14.01.2016, 10:26 #43
Цитата Сообщение от mporro Посмотреть сообщение
Также и с конструкторами: они не наследуются, наследовать их было бы крайне глупо, но они агрегируются.
Ну, Страуструп мастер засирать мозги, и его терминология очень противоречива. Изначально наследование означает наследование свойств, однако при закрытом наследовании классов этого не происходит.
Наследование функции, это когда несколько классов разного типа имеют одну и ту же функцию. Но конструкторы классов разных типов по определению имеют разные имена, как же два разных типа могут иметь один и тот же конструктор?
Так что холивар заложен самим автором языка в его противоречивой терминологии.
0
mporro
256 / 102 / 14
Регистрация: 04.07.2014
Сообщений: 571
14.01.2016, 10:30 #44
hoggy
Опять у фас какие-то фантазии начинаются, на почве С++

Согласно вашим фантазиям ниже идёт наследование...
C++
1
2
3
4
5
6
7
8
struct TBase {
    void foo();
};
 
struct TDerived {
    TBase b;
    void baz();
};
0
Mr.X
Эксперт С++
3049 / 1694 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
14.01.2016, 10:33 #45
Цитата Сообщение от mporro Посмотреть сообщение
Можно развести дискуссию и на такую тему, что обсуждение наследования конструктора бессмысленно, как деление ноль, так как нельзя сказать, что объект обрабатывает сообщение о своём конструировании, ведь он вообще не создан!
Ну, конструктор инициализирует уже созданный объект, поэтому его можно рассматривать как сообщение "сырому" объекту.
Кстати, здесь у Страуструпа тоже терминологический ляп, так как конструктором он назвал то, что фактически является инициализатором.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.01.2016, 10:33
Привет! Вот еще темы с ответами:

Конструкторы и деструкторы - C++
Код: #include &lt;iostream&gt; #include &lt;stdlib.h&gt; #include &lt;conio.h&gt; class complex { private: double im; double...

Конструкторы и деструкторы - C++
Помогите исправить программу. Необходимо реализовать класс с двумя полями, имеющими имена first и second. Обязательно должны...

Конструкторы и деструкторы - C++
Прочитал про конструкторы и деструкторы. Пишут что они нужны для инициализации переменных класса. Как они используются я понял, но не понял...

Конструкторы и деструкторы - C++
Привет. Есть структура, содержащая 7 полей, в которые я ввожу значения с клавиатуры. Нужно используя конструкторы и деструкторы...


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

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

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