Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 20.04.2018
Сообщений: 38

Преобразование ссылки на дочерний класс в ссылку также на дочерний класс

28.04.2020, 23:15. Показов 2046. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Имеются 3 класса: Базовый класс Person9 и два производных(дочерних) от него Official9 и Student9
Необходимо через dynamic_cast преобразовать ссылку на класс Official9 в ссылку на класс Student9, помогите пожалуйста как это можно сделать?
Пытался напрямую (см. код главной программы), как если бы преобразовывал ссылку на базовый класс в ссылку на дочерний, но в таком случае натыкаюсь на ошибку: "E0434 не удается инициализировать ссылку типа "Official9 & (квалифицируется как неконстантная) со значением типа "Student9"

Описание классов:
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Person9
{
protected:
    string Name;
    string Second_name;
    short Age;
public:
    Person9() {};
    Person9(string nm, string s_nm, short ag)
    {
        Name = nm; Second_name = s_nm; Age = ag;
    };
    virtual void Out()
    {
        cout << "Имя: " << Name << "; Фамилия: " << Second_name << "; Возраст: " << Age << endl;
    }
};
 
class Official9 :public Person9
{
    string Specialty;
public:
    Official9(string nm, string s_nm, short ag, string sp) : Person9(nm, s_nm, ag)
    {
        Specialty = sp;
    }
    void Out()
    {
        cout << "Имя: " << Name << "; Фамилия: " << Second_name << "; Возраст: " << Age << "; Специальность: " << Specialty << endl;
    }
};
 
class Student9 : public Person9
{
    string Group;
    double Average;
public:
    Student9(string nm, string s_nm, short ag, string grp, double avrg) : Person9(nm, s_nm, ag)
    {
        Group = grp;
        Average = avrg;
    }
    void Out()
    {
        cout << "Имя: " << Name << "; Фамилия: " << Second_name << "; Возраст: " << Age << "; Группа: " << Group << "; Средний балл: " << Average << endl;
    }
};
Главная программа:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main()
{
    setlocale(LC_ALL, "rus");
        cout << endl << endl << "Задание 9" << endl;
    Person9 pers9("person9", "person99", 18);
    Official9 ofcl9("name9", "second_name9", 100, "speciality");
    Student9 std9("name.std9", "second_name.std9", 1, "group", 5);
    try 
    {
        //Моя попытка преобразование ссылки на класс Official9 в ссылку на класс Student9:
        Student9& std9_ref = std9;
        Official9& ofcl99_ref = std9_ref; //<-- здесь ошибка E0434 не удается инициализировать ссылку типа "Official9 & 
                                                       //(квалифицируется как неконстантная) со значением типа "Student9"
 
        dynamic_cast<Student9&>(ofcl99_ref).Out();
    }
    catch (std::bad_cast)
    {
        cout << " BAD CAST 1 ";
    }
 
    return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
28.04.2020, 23:15
Ответы с готовыми решениями:

Класс млекопитающих: создать дочерний класс кошка, который также характеризуется именем и положением в пространстве
Есть класс млекопитающих. Он у меня характеризуется именем и положением в пространстве. Хочу создать дочерний класс кошка, который также...

Дочерний класс
Просьба обьяснить (((и привести пример))) дочернего и родительского класса!!!

Указатель на дочерний класс
Доброго времени суток! Есть класс TSpisok в нём должны быть поля указатели на первый,текущий,последний элемент TElement. Попытался сделать...

19
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
28.04.2020, 23:23
MrTomCheket, зачем это вам понадобилось? Опишите дальнейшие действия.
Преобразование которого вы хотите незаконно.
0
0 / 0 / 0
Регистрация: 20.04.2018
Сообщений: 38
28.04.2020, 23:27  [ТС]

понадобилось из-за задания в лабораторке по ООП
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
28.04.2020, 23:27
Цитата Сообщение от MrTomCheket Посмотреть сообщение
Необходимо через dynamic_cast преобразовать ссылку на класс Official9 в ссылку на класс Student9, помогите пожалуйста как это можно сделать?
C++
1
2
3
4
5
6
    try
    {
        //Моя попытка преобразование ссылки на класс Official9 в ссылку на класс Student9:
        Official9& ofcl99_ref = ofcl9;
        Student9& std9_ref = dynamic_cast<Student9 &>(ofcl99_ref);
    }
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
28.04.2020, 23:38
MrTomCheket, метод out объявите виртуальным в базовом. А в наследниках реализуйте. Вызывать через ссылку на базовый.
0
0 / 0 / 0
Регистрация: 20.04.2018
Сообщений: 38
28.04.2020, 23:43  [ТС]
oleg-m1973, Исправил как вы указали, ошибка E0434 пропала, но теперь при компиляция срабатывает обработка исключений и выводится " BAD CAST 1 ", если же убрать try-catch, то появляется ошибка в окне "Microsoft Visual C++ Runtime Library Debug Error!"
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
28.04.2020, 23:45
Цитата Сообщение от MrTomCheket Посмотреть сообщение
oleg-m1973, Исправил как вы указали, ошибка E0434 пропала, но теперь при компиляция срабатывает обработка исключений и выводится " BAD CAST 1 ", если же убрать try-catch, то появляется ошибка в окне "Microsoft Visual C++ Runtime Library Debug Error!"
Всё правильно, должно выводится BAD CAST 1. Так и было задумано, насколько я понимаю - чтобы показать, что некорректное преобразование будет обнаружено в рантайме.
0
0 / 0 / 0
Регистрация: 20.04.2018
Сообщений: 38
28.04.2020, 23:51  [ТС]
oleg-m1973, либо я неправильно понял задание и действительно нужно сделать так, как Вы говорите, либо нужно всё-таки каким-то образом реализовать преобразование ссылки на дочерний класс в ссылку также на дочерний класс, но насколько я понял, это сделать невозможно?

Задание в лабораторной так и звучит: Обеспечить преобразование ссылки на класс служащий в ссылку на класс студент
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
28.04.2020, 23:53
Цитата Сообщение от MrTomCheket Посмотреть сообщение
Задание в лабораторной так и звучит: Обеспечить преобразование ссылки на класс служащий в ссылку на класс студент
Для этого нужно, чтобы служащий наследовался от студента или наоборот.
0
0 / 0 / 0
Регистрация: 20.04.2018
Сообщений: 38
29.04.2020, 00:00  [ТС]
IGPIGP,
Цитата Сообщение от IGPIGP Посмотреть сообщение
метод out объявите виртуальным в базовом. А в наследниках реализуйте.
метод out в базовом классе уже был объявлен как виртуальный, и кажется он также уже был реализован в наследниках, либо я не понял о что вы имели в виду.

Цитата Сообщение от IGPIGP Посмотреть сообщение
Вызывать через ссылку на базовый.
Не совсем понимаю как это сделать

Добавлено через 50 секунд
oleg-m1973, видимо действительно необходимо переделать в этом задании иерархию данных классов, просто в предыдущих заданиях этой лабораторной иерархия должна была быть именно такой, как я описал в начале, то есть базовый Person и два дочерних ему Student и Official. Нужно будет уточнить задание у преподавателя.
Спасибо за помощь!
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
29.04.2020, 00:07
Цитата Сообщение от MrTomCheket Посмотреть сообщение
Не совсем понимаю как это сделать
В этом нет зла как такового, но сам его корень (зла), имхо, именно в этом.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
29.04.2020, 00:21
Цитата Сообщение от MrTomCheket Посмотреть сообщение
oleg-m1973, видимо действительно необходимо переделать в этом задании иерархию данных классов, просто в предыдущих заданиях этой лабораторной иерархия должна была быть именно такой, как я описал в начале, то есть базовый Person и два дочерних ему Student и Official. Нужно будет уточнить задание у преподавателя.
Основное отличие dynamic_cast от static_cast это то, что первый умеет отлавливать некорректное преобразование в рантайме. И, либо вызывать std::bad_cast в случае ссылки, либо возвращать nullptr в случае указателя.
Подозреваю, исследовать такое поведение и было заданием. Единственно, надо сначала преобразовать Official9 -> Person9, а потом Person9 -> Student9
C++
1
2
3
4
5
6
    try
    {
        //Моя попытка преобразование ссылки на класс Official9 в ссылку на класс Student9:
        Person9 &ofcl99_ref = ofcl9;
        Student9 &std9_ref = dynamic_cast<Student9 &>(ofcl99_ref);
    }
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
29.04.2020, 02:03
Цитата Сообщение от MrTomCheket Посмотреть сообщение
Имеются 3 класса: Базовый класс Person9 и два производных(дочерних) от него Official9 и Student9
Необходимо через dynamic_cast преобразовать ссылку на класс Official9 в ссылку на класс Student9, помогите пожалуйста как это можно сделать?
Это прямо так и делается

C++
1
2
3
Official9 &official = ...;
 
Student9 &student = dynamic_cast<Student9 &>(official);
Все. Если ваши классы удовлетворяют требованиям dynamic_cast, то преобразование выполнится успешно. А именно: исходная ссылка Official9 & должна ссылаться на public базовый подобъект типа Official9 в составе некоторого большего объекта типа T, у которого также есть и однозначный public базовый подобъект типа Student9. То есть dynamic_cast позволит вам в такой ситуации выполнить cross-cast: "прыгнуть" с одной базы общего потомка типа T на его другую базу.

Подчеркиваю: такой dynamic_cast всегда работает "через низ", т.е. через общего потомка T, а не через общего предка.

Однако в вашей иерархии классов это преобразование никак не может быть успешным. У вас не нигде не видно такого типа T, являющегося общим потомком. А без этого о таком преобразовании не может быть и речи - вы будете просто получать от dynamic_cast исключения std::bad_cast. То есть пока у вас не появится

C++
1
2
class OfficialStudent9 : public Official9, public Student9
{
такой dynamic_cast всегда будет завершаться безуспешно.

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Единственно, надо сначала преобразовать Official9 -> Person9, а потом Person9 -> Student9
Нет, ничего подобного в dynamic_cast не требуется. См. выше. Эти классы могут не иметь общего предка вообще.

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Для этого нужно, чтобы служащий наследовался от студента или наоборот.
Нет, требования dynamic_cast более "свободны": для этого нужно чтобы они оба входили в состав одного потомка и исходная ссылка ссылалась внутрь такого потомка.
1
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
29.04.2020, 11:01
Хотя, конечно удивляет, что вообще можно скомпилировать dynamic_cast из Official9& в Student9& - если эти типы нельзя преобразовать в compile-time, то какой смысл проверять это в рантайме?
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
29.04.2020, 11:09
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Хотя, конечно удивляет, что вообще можно скомпилировать dynamic_cast из Official9& в Student9& - если эти типы нельзя преобразовать в compile-time, то какой смысл проверять это в рантайме?
Мой MinGW фыркает варнингом, о том что такое преобразование не имеет вариантов успешного исхода но компилириует. Я думаю, - он тоже вовлечён в учебную программу "Бодни монитор и посмотри на результат". А ведь монитор не может выздороветь, в отличие от головы. Я тоже не понимаю.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
29.04.2020, 11:33
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Хотя, конечно удивляет, что вообще можно скомпилировать dynamic_cast из Official9& в Student9& - если эти типы нельзя преобразовать в compile-time, то какой смысл проверять это в рантайме?
А с чего вы взяли, что функциональность dynamic_cast должна сводиться лишь к проверкам того, что можно преобразовать в compile-time? Вы, как я понимаю, никогда его ни для чего другого не использовали и для вас полный спектр его возможностей является сюрпризом.

dynamic_cast в общем случае базируется на RTTI и может делать особые, чисто RTTI-шные трюки. В частности, dynamic_cast умеет находить most derived object через преобразование к void *. Это уже - новая функциональность, недоступная compile-time кастам. А там где есть возможность находить most derived object, там открываются возможности и для cross-cast через этот most derived object.

Опять же, если бы вы знали общего потомка заранее, вы бы смогли преобразовать эти типы в compile-time, двумя кастами: downcast к общему потомку и последующий upcast. Без проверки правильности, разумеется. А dynamic_cast просто делает это за один шаг, плюс выполняет проверку.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
29.04.2020, 11:41
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
А с чего вы взяли, что функциональность dynamic_cast должна сводиться лишь к проверкам того, что можно преобразовать в compile-time? Вы, как я понимаю, никогда его ни для чего другого не использовали и для вас полный спектр его возможностей является сюрпризом.
Ну, я вообще никогда не использовал dynamic_cast, как-то не было необходимости.
Но, тем не менее, искренне не понимаю - если указатели указывают на абсолютно разные классы, и их нельзя преобразовать в compile-time при помощи static_cast, то каким образом это можно сделать в рантайме?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
29.04.2020, 12:01
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Но, тем не менее, искренне не понимаю - если указатели указывают на абсолютно разные классы, и их нельзя преобразовать в compile-time при помощи static_cast, то каким образом это можно сделать в рантайме?
Это преобразование можно сделать в рантайме тогда и только тогда, когда это потенциально можно сделать и в compile-time: когда у классов существует общий потомок. Когда существует общий потомок, преобразование вполне возможно через два compile-time каста.

Разница только в том, что для compile-time преобразования вам нужно в мемюсте выполнения каста знать и видеть тип этого общего потомка.

А dynamic_cast, благодаря RTTI, имеет возможность это сделать без знания и видения типа этого общего потомка.

Вот и вся разница.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
29.04.2020, 12:08
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Это преобразование можно сделать в рантайме тогда и только тогда, когда это потенциально можно сделать и в compile-time: когда у классов существует общий потомок.
И какой смысл доводить до рантайма то, что заведомо выдаст ошибку? Например, вот такой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        struct A
        {
            virtual ~A() { ; }
            std::set<int> m_items;
        };
 
        struct B
        {
            virtual ~B() { ; }
            std::string m_s;
        };
 
        A a;
        auto &b = dynamic_cast<B &>(a);
Да, здесь dynamic_cast выдаст исключение. Но это было понятно на этапе компиляции. Зачем его вообще компилировать без ошибок (в студии и без предупреждений)?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12938 / 6805 / 1821
Регистрация: 18.10.2014
Сообщений: 17,224
29.04.2020, 12:24
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Да, здесь dynamic_cast выдаст исключение. Но это было понятно на этапе компиляции. Зачем его вообще компилировать без ошибок (в студии и без предупреждений)?
Я вижу, вы застряли на тривиальных примерах и не понимаете всей полноты картины.

Где-то на другом конце программы, в другой единице трансляции, Вася Пупкин может создать свой великий ультра-класс, который наследуется одновременно от вашего A и от вашего B. После чего он создаст экземпляр этого великого класса, возьмёт ссылку на базу A и передаст ее вам сюда, в вашу единицу трансляции.

И здесь вы будете делать dynamic_cast этой ссылки из A& в B&. И этот dynamic_cast обязан отработать успешно, без выбрасывания исключений, и отработать корректно, несмотря на то, что в этой единице трансляции вы ничего не знаете о великом ультра-классе Васи.

Так что смотря только на эти два класса, которые вы привели, или (шире) даже на всю вашу единицу трансляции невозможно сделать никаких выводов о возможности или невозможности такого каста.

Предсказать безуспешность каста можно только в том случае, если вы четко видите происхождение исходной ссылки (как в вашем тривиальном примере) и, поэтому, точно знаете, что ни в какой Васин ультра-класс она не ссылается.

Но как только происхождение ссылки становится туманным (например, это параметр внешней функции), то никаких предсказаний сделать невозможно. Каст вполне может быть корректным.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
29.04.2020, 12:24
Помогаю со студенческими работами здесь

Дочерний класс от QByteArray
Хочу унаследовать класс от QByteArray и переопределить там метод append(QByteArray&amp; ba). Необходимо проведение определенных проверок над...

Дочерний и родительский класс
Всем привет!!! помогите кто чем может ) Нужно создать родительский класс треугольник(или что типо того) и к нему подключить дочерний класс...

Родительский и дочерний класс
Передо мной была поставлена задача создать родительский класс (какуюто фигуру) и к нему подклю4ить дочерний класс (так же какаюто фигуру).и...

Родительский и дочерний класс
Всем доброго времени суток. Возникла проблема; //file Base.h #include &quot;Children.h&quot; class Base { public: Children* a; } //file...

Наследование - дочерний класс
Помогите разобраться: Выношу в дочерний класс часть расчета пользуюсь только: public class abc extends cba{ Все переменные у меня...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru