0 / 0 / 0
Регистрация: 25.07.2020
Сообщений: 36
|
||||||
1 | ||||||
При создании объекта наследуемого класса не срабатывает конструктор родительского класса19.01.2021, 01:41. Показов 2300. Ответов 10
Уважаемые, эксперты! Суть простая.
1. Есть базовый класс String. В нём массив фиксированной длины, которая задана константой SZ. При вызове ктора с аргументом типа const char[] указанный массив инициализируется (т.е. содержимое аргумента-массива копируется в массив являющийся атрибутом объекта класса) 2. Есть производный от String класс class Pstring: public String {}, который единственно что делает, - это перегружает к-тор базового класса (также с аргументом const char[]), НО УЖЕ ПРОВЕРЯЯ при этом ДЛИНУ ПОДАВАЕМОГО АРГУМЕНТА с помощью strlen. Дальше условие: а. Если strlen(аргумента) >= SZ-1, копируем в массив объекта производного класса ТОЛЬКО (SZ-1) символ, т.е. чтобы избежать переполнения буфера отсекаем, то что не влезет б. Иначе (т.е. strlen(аргумента)<SZ-1, а значит в исходный массив должна влезть вся строка) просто вызваю ктор родительского класса, чтоб он сам создал и проинициализировал тот же массив, т.е. копирование делать как бы незачем его и так должен выполнить к-тор род. класса. Проблема в том что в ветке б. передаваемое значение строки в массив объекта производного класса почему то не заносится т.е. строка выводится пустая, а значит родительский к-тор с аргументом не сработал или сработал некорректно! Возможно срабатывает безаргументный к-тор род. класса но непонятно почему ведь вызов идёт в явном виде String(s); В чём м.б. проблема или так вобще некорректно использовать родительский ктор?! П.С. Пример этот из книги Лафоре, но даже будучи скопированным один в один нужного рез-та не возникает, как раз в том случае, когда подаваемую строку даже не надо обрезать по длине, а вот если она длинней лимита SZ всё создаётся и копируется!
0
|
19.01.2021, 01:41 | |
Ответы с готовыми решениями:
10
ООП в C++: Вызов родительского конструктора с параметром при создании объекта дочернего класса Что значит конструкция при создании наследуемого класса от QMainWindow Использование объекта одного класса при создании нового класса Вызвать конструктор наследуемого класса в абстрактом родителе |
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
|
|
19.01.2021, 04:07 | 2 |
Тут String(s); - не вызов конструктора, а создание безымянного объекта типа String.
Когда вы попали в тело конструктора Pstring, базовый класс уже создан. Единственным мне известный способ вызова родительского конструктора - в списке инициализации наследника.
1
|
Вездепух
12794 / 6671 / 1795
Регистрация: 18.10.2014
Сообщений: 16,890
|
|
19.01.2021, 04:12 | 3 |
В С++ вообще не существует способа явно вызвать конструктор (кроме разве что делегации конструкторов). Потому что вы имеете в виду под "просто вызваю ктор родительского класса" - не ясно. Ваше
String(s); - это никакой не вызов конструктора родительского класса.
1
|
0 / 0 / 0
Регистрация: 25.07.2020
Сообщений: 36
|
|
19.01.2021, 05:40 [ТС] | 4 |
Ну я так и подозревал. На самом деле меня конструкция типа String(s) уже в {} после списка инициализации тоже смущала несколько. Как будто безымянный объект род. класса возник внутри объекта класса производного. Такой не очевидный код.
Поэтому я сначала сделал также через копирование, но в решении в книге увидел именно такой более короткий ход с вызовом String(s) именно внутри тела к-тора производного класса. Я так и стал пробовать и очень удивился, что не сработало. Книга старая, возможно старый стандарт когда то допускал такое... Ну если поставить это в лист инициализации к-тора производного класса, то будет именно вызов к-тора род. класса. Это ведь как раз то что вы имеете ввиду, когда говорите про "делегацию к-ов" или нет? Не совсем понятно почему в теле к-тора это должно работать по-другому... Ну что ж, в любом случае это так. Значит в листинге книги ошибка. Вот и всё тут. Добавлено через 5 минут Скорее всего вы имели ввиду не класс, а объект, ибо класс же только дефиниция, а память реально выделяется только, когда объявляется объект этого класса, разве нет? И вот я не понял, как это он такой объект род. класса м.б. уже создан при входе в к-тор Pstring, если инициализации перед скобками не было? Ведь в производном классе у меня стоит "свой" перегруженный к-тор с входным параметром. Лист инициализации был пуст. Получается, что на момент входа в тело к-тора Pstring(const char[]) ни один из к-торов род. класса ещё не должен был отработать...
0
|
Вездепух
12794 / 6671 / 1795
Регистрация: 18.10.2014
Сообщений: 16,890
|
|
19.01.2021, 05:44 | 5 |
Нет, старый стандарт никогда такого не допускал. В том смысле, что такой синтаксис всегда просто создавал временный объект.
Это будет инициализация родительского класса в списке инициализации конструктора производного класса. А то, что эта инициализация приводит в том числе к вызову конструктора родительского класса - это уже дело третье, следствие процесса инициализации. Нет. Делегация конструкторов - это фича С++11, когда конструктор класса может вызвать другой конструктор этого же класса.
1
|
3718 / 2647 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
|
||||||
19.01.2021, 15:08 | 6 | |||||
Не по теме: А вызов конструктора в теле конструктора возможна в других языках. Добавлено через 6 минут Приведите пример.
0
|
1659 / 488 / 106
Регистрация: 17.05.2015
Сообщений: 1,497
|
||||||
19.01.2021, 15:15 | 7 | |||||
0
|
610 / 415 / 151
Регистрация: 11.01.2019
Сообщений: 1,746
|
|
19.01.2021, 15:35 | 8 |
Сообщение было отмечено realalexandro как решение
Решение
realalexandro, всё же очевидно! У тебя конструктор производного класса неявно вызывает дефолтный конструктор базового класса, а не тот, что со строкой в параметре. Объект ex1 потом заполняется строкой, т.к. выполняется условие в строке 41, а объект ex2 остается пустым, т.к. это условие не срабатывает. В строке 45 при этом создается какой-то временный пустой объект, никак не связанный с ex1, ex2.
0
|
0 / 0 / 0
Регистрация: 25.07.2020
Сообщений: 36
|
|
19.01.2021, 17:59 [ТС] | 9 |
Почему же срабатывает именно дефолтный к-тор без строки в параметре, когда инструкция идёт String(s); , а не просто String();
Я же передаю в род. к-тор именно параметр s, предполагая, что компилятор подставит, как раз родительский НЕ дефолтный к-тор, а параметрический. Иначе зачем я передаю строку s, если она никуда не идёт?! Я понимаю, что работает именно так, как ты описал. Не понимаю только почему хотя бы не создаётся объект род. класса, НО ПРОИНИЦИАЛИЗИРОВАННЫЙ ИМЕННО СТРОКОЙ s! Добавлено через 6 минут Или он его по-любому вызывает ещё до проверки условий? Т.е. даже если в строке инициализации производного класса никакого к-тора явно не указано, то поскольку этот класс производный при объявлении объекта производного всегда будет запускаться "пустой" к-тор родительского класса до любых ручных манипуляций, так я понимаю? Ну тогда да, безымянный объект String(s) как бы повисает в пустоте и не участвует в инициализации того производного объекта, который я пытаюсь инициализировать...
0
|
610 / 415 / 151
Регистрация: 11.01.2019
Сообщений: 1,746
|
|
19.01.2021, 18:33 | 10 |
Увы, но компилятор такого замысла не понимает и подставляет дефолтный конструктор.
Да. Это совершенно независимый временный объект базового класса.
0
|
Вездепух
12794 / 6671 / 1795
Регистрация: 18.10.2014
Сообщений: 16,890
|
|
19.01.2021, 19:09 | 11 |
Не понял. Какой конструктор базового класса будет вызван определяется списком инициализации класса-населдника. У вас там нет вообще никаких "инструкций" для базового класса. Потому и вызывается конструктор по умолчанию.
Вы о чем? О вашем String(s); в теле конструктора? Как же было сказано выше, это создание постороннего временного объекта типа String . Все тут прекрасно передается, вызывается конструктор String(const char s[]) . О каком "никуда не идёт" вы ведете речь?Откуда вы это взяли? Все прекрасно создается! Создаётся временный объект родительского класса, проинициализированный именно строкой s . После чего он сразу же удаляется. Это посторонний временный объект, который в вашем коде ни на что не влияет.
0
|
19.01.2021, 19:09 | |
19.01.2021, 19:09 | |
Помогаю со студенческими работами здесь
11
Ошибка при создании объекта класса Ошибка при создании объекта класса Ошибка при создании объекта класса Ошибка при создании объекта класса Не могу передать параметр в родительский конструктор при создании экземпляра класса Конструктор родительского класса с аргументом Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |