Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.57/30: Рейтинг темы: голосов - 30, средняя оценка - 4.57
0 / 0 / 0
Регистрация: 18.09.2018
Сообщений: 4

Восходящее преобразование массива производного класса к родительскому?

03.01.2020, 22:54. Показов 7450. Ответов 114

Студворк — интернет-сервис помощи студентам
Есть два класса base_Class(родитель) и derived_Class(потомок)
Есть некая виртуальная функция в base_Class которая принимает в качестве параметра массив объектов класса f(base_Class **mass)
Чтобы воспользоваться данной функцией для производного класса, необходимо привести массив производного класса к массиву родительского
Массивы: base_Class *baseMass[100], derived_Class *derivedMass[100]
Как произвести такое приведение типов?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
03.01.2020, 22:54
Ответы с готовыми решениями:

Определить обработчик исключений на преобразование указателя базового класса на указатель производного класса
Класс В является производным от класса А. Определить обработчик исключительной ситуации на преобразование указателя базового класса А на...

Восходящее преобразование
помогите пожайлуста разобраться, почему выдаёт ошибку... public class A{ public int f1(){return 1;}; public int...

Восходящее преобразование, объяснить код
Всем привет! Мне не понятен один момент в восходящем преобразовании. Есть два класса: один базовый, другой производный от базового. В...

114
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
07.01.2020, 00:21
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от IGPIGP Посмотреть сообщение
Что касается P и Q то я их упоминал совместно чтобы было понятно что речь о адресном выражении для обращения к элементу в соответствии с текстом цитаты из стандарта (пардон - черновика), потому как просто P выглядит куцо.
Там не может быть P и Q, additive operator перегружен только для случаев когда:
1) Оба операнда arithmetic or unscoped enumeration type.
2) Один из операндов указатель, а другой integral or unscoped enumeration type (наш случай).
Т.е. у нас может быть только P + n, где n - integral or unscoped enumeration type.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
07.01.2020, 00:32
Цитата Сообщение от Azazel-San Посмотреть сообщение
Т.е. у нас может быть только P + n,
Azazel-San, Я привёл их потому что P упомянут в тексте вместе с Q в первом упоминании. В настоящей НТД (как инженер говорю, кстати) первое упоминание делается с использованием псевдонима словами "именуемого в дальнейшем..." или "далее по тексту..." и проще ссылаться. Вот и всё. Если от этой пары у вас плохие ассоциации - замените всё на P.
К тому же тест выделенный в цитате (см. ссылку) упоминает оба
For addition or subtraction, if the expressions P or Q have type “pointer to cv T”, where T and the array element type are not similar, the behavior is undefined. [ Note: In particular, a pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type.  — end note ]
И тут UB касается именно адресной арифметики с участием P or Q .
И ограничение на адресную арифметику (пусть даже наш случай P+n или Q+n) выделены именно для типов а не указателей иерархии.
Больше вопросы о том зачем Q не принимаю.
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
07.01.2020, 00:38
Цитата Сообщение от hoggy Посмотреть сообщение
ты сохраняешь в указателе значение объекта, имеющего тип X*
(а не тип Y*)
Статический будет X, а динамический Y, не?
Ну, rat0r говорил что нарушение если:
Цитата Сообщение от rat0r Посмотреть сообщение
Здесь нет доступа к объекту (чтения) с типом Y* через glvalue с типом X*.
У меня в коде
X* xp - xp это glvalue с типом X*.
А xp->f() это попытка доступа к объекту (чтения) с типом Y.
А надо было, что бы чтение было с типом Y*?
там уже кидал вроде как "верный" вариант)

Добавлено через 3 минуты
Цитата Сообщение от IGPIGP Посмотреть сообщение
Если от этой пары у вас плохие ассоциации - замените всё на P.
Да, есть такое, причем постоянно при чтении стандарта )
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.01.2020, 00:40
Цитата Сообщение от Azazel-San Посмотреть сообщение
Статический будет X, а динамический Y, не?
не.

смотри:

C++
1
X* p = &y;
тоже самое что:

C++
1
X* p = static_cast<X*>(&y);
компилятор сначала приводит правую часть к такому же типу, что слева.
и уже только затем засовывает результат преобразования в указатель p

Добавлено через 1 минуту
Цитата Сообщение от Azazel-San Посмотреть сообщение
Ну, rat0r говорил что нарушение если:
дык, он вырыжается как аутист.

я подозреваю что он имел ввиду это:
Восходящее преобразование массива производного класса к родительскому?
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.01.2020, 00:53
Цитата Сообщение от Azazel-San Посмотреть сообщение
Значит строка (*xpp)->f() нарушает strict aliasing rule?
Да. Подвыражение *xpp это lvalue с типом X*, которое обозначает объект yp типа Y* (т.к. у xpp значение "указатель на объект yp").
Когда к этому подвыражению применяется lvalue-to-rvalue conversion, происходит чтение значения обозначаемого объекта yp. Чтение — это доступ. И он происходит через lvalue с типом, который не является similar to тип, который это lvalue обозначает.

Добавлено через 3 минуты
Цитата Сообщение от hoggy Посмотреть сообщение
А ты сообразительный. Начал подозревать что я имел ввиду всего-то через 20 сообщений после того, как я явно написал, что имел в виду Восходящее преобразование массива производного класса к родительскому?
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.01.2020, 00:59
Цитата Сообщение от rat0r Посмотреть сообщение
А ты сообразительный. Начал подозревать что я имел ввиду всего-то через 20 сообщений после того, как я явно написал,
нет.
подозревать я начал уже вот здесь:
Восходящее преобразование массива производного класса к родительскому?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
struct base
{
    virtual ~base(){}
    virtual void foo(){ std::cout << "base::foo()\n"; }
    int v = 3;
};
 
struct der: base
{
    virtual void foo(){ std::cout << "der::foo()\n"; }
    int w[100];
};
 
 
int main()
{
    der d;
    der* p = &d;
    base* b = reinterpret_cast<base*>(p); // <--- не является similar 
    b->foo();
}
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.01.2020, 01:04
Цитата Сообщение от IGPIGP Посмотреть сообщение
Я привёл их потому что P упомянут в тексте вместе с Q в первом упоминании.
Первое упоминание P в 4-м параграфе, P вместе с Q — в пятом. А про UB написано в шестом.
Цитата Сообщение от IGPIGP Посмотреть сообщение
К тому же тест выделенный в цитате (см. ссылку) упоминает оба
Да, мы уже поняли, что ты тащишь и выделяешь всё что угодно из параграфа, даже если оно нерелевантно. Просто потому что оно там есть.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
07.01.2020, 01:40
Цитата Сообщение от rat0r Посмотреть сообщение
Да, мы уже поняли,
Вас много? rat0r, если вы заметили я настолько не возражаю, что обращаюсь к вам на вы. От вас подобного не могу ожидать. Однако выделено зелёным маркером это не мной. Посмотрите цитату ещё раз. Вы говорили о чтении чего-то куда-то. И я пытался в терминах цитаты реагировать на ваше высказывание. Там P (без Q чтобы вам легче было) используется для доступа, а чтение делается из элементов. Эту мысль я и пытался высказать.
Там есть момент о котором никто почему-то не говорит.
Azazel-San, обратите внимание.
Цитата Сообщение от IGPIGP Посмотреть сообщение
In particular, a pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type.
И тут всё ясно. О проблеме усечения при создании смешанных массивов по значению предупреждал Скотт Мейерс, например.
C++
1
2
3
Base bs1, bs2;
Derived dr1, dr2;
Base base_mixed[]={bs1, bs2, dr1, dr2};//как видите компилируется
Это не должно бы компилироваться (имхо в языке с строгой типизацией, как было отмечено), но язык это допускает. Если наследники больше - будут усечены. Деструкторы для них будут вызваны не родные. Уродство иными словами. Но именно этот случай и описан в цитате. Речь идёт о элементах массива - объектах иерархии. Не о элементах указателях.
Это справедливости ради - имея ввиду цитату. Не для того чтобы выцепить неудобно склизкий момент.
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.01.2020, 03:44
Цитата Сообщение от IGPIGP Посмотреть сообщение
Вас много?
Видимо. Ты же "выкаешь" постоянно.
Цитата Сообщение от IGPIGP Посмотреть сообщение
Однако выделено зелёным маркером это не мной.
Что поделать, так устроен тот html-драфт, на который я сослался. Что зелёным подсвечивается весь параграф. Если для тебя это оправдание твоего неумения понимать что релевантно, а что нет — ок.
Цитата Сообщение от IGPIGP Посмотреть сообщение
Если наследники больше - будут усечены. Деструкторы для них будут вызваны не родные.
В каком смысле "не родные"? Для элементов массива с типом Base будут вызваны их родные деструкторы Base::~Base.
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но именно этот случай и описан в цитате
У тебя Base от Derived наследуется, что ли?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
07.01.2020, 11:42
Цитата Сообщение от rat0r Посмотреть сообщение
Видимо. Ты же "выкаешь" постоянно.
rat0r, ваша проницательность на высоте. Давайте поиграем на вашем поле (на моём вы не любите играть). То есть, без следов мысли мы поиграем в цитаты по вопросу о том сколько нас. Давайте? Я цитирую;
Цитата Сообщение от rat0r Посмотреть сообщение
Да, мы уже поняли, что ты тащишь и
Тут вы недвусмысленно говорите о том что вас много. А ко мне обращаетесь на ты подчёркивая, что меня мало.
Теперь посовещайтесь и приведите наиболее яркие мои слова, которые свидетельствуют о том, что мне вас следует называть на ты. Или что меня много. Или что по русски, обращение на ты свойственно нормальным людям, которые друг друга не знают.
Цитата Сообщение от rat0r Посмотреть сообщение
Что поделать, так устроен тот html-драфт, на который я сослался. Что зелёным подсвечивается весь параграф. Если для тебя это оправдание твоего неумения понимать что релевантно, а что нет — ок.
rat0r, я не считаю главу НТД набором несвязных сентенций. Хотя с драфтом это похоже на правду. Во всяком разе кто-то посчитал нужным выделить зелёным тот кусочек в кусочке, что вы привели. А вы могли бы точнее ограничить объём цитирования (или хотя бы отметить тот факт что де террористы облили зелёнкой текст и не нужно обращать внимания). И пояснять свою мысль. Тогда было бы проще понять эту вашу мысль.
А иной раз вы цитируете гораздо меньше чем достаточно, чтобы не только понять за чем вы это цитируете, а и найти релевантное место.
Например:
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но именно этот случай и описан в цитате.
Его и мне трудновато было отыскать. Но нас (с вами) же тут читают и другие. Их таки много и они заслуживают уважения.
Я покажу как надо:
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но именно этот случай и описан в цитате. Речь идёт о элементах массива - объектах иерархии. Не о элементах указателях.
Это справедливости ради - имея ввиду цитату. Не для того чтобы выцепить неудобно склизкий момент.
Эти слова связаны с текстом:
Цитата Сообщение от IGPIGP Посмотреть сообщение
pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type.
И подстверждены (слова) кодом. Он компилируется. Мейерс упоминает вектор но не суть. С массивом тоже получается. В вашем приведенном куске мира html-драфт это отмечено.
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
07.01.2020, 16:41
Цитата Сообщение от IGPIGP Посмотреть сообщение
pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type.
И подстверждены (слова) кодом. Он компилируется.
Любой код, который компилируется, является примером для этой цитаты?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
07.01.2020, 19:55
Цитата Сообщение от rat0r Посмотреть сообщение
Любой код, который компилируется, является примером для этой цитаты?
Это же логика rat0r. Причём не в коде, а в языке. Любой, это какой бы то ни было. А некоторый, это один из. В булевых выражениях оно конечно понятнее, потому, что в человеческим языке это требует владения человеческим языком.
Когда я сам писал НТД пришлось так много пообщаться с нормативщиками, что приходя домой я говорил жене "необходимо предусмотреть наличие кипятка для приготовления чая". Это был кошмар. Но я научился понимать язык на котором пишут документы на основании которых могут решаться споры между проэктировщиком и производителем и/или ими обоими или кем-то из них и потребителем при авариях с нанесением ущерба и/или человеческими жертвами. Там где их пишут, понимают что нормативный текст это нормативная лексика, а нормативный документ это всё что в нём есть. Это текст, графика, таблицы и пр. Там вот за такую фразу секут пониже спины:
Цитата Сообщение от песнь непуганных идиотов
In particular, a pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type.
Тут сказано буквально:
В частности, укзатель на базовый класс не может быть использован для адресной арифметики если массив содержит объекты наследующего класса.
Нужно отметить, что
если массив содержит
хороша. Она говорит что массив не обязан состоят из . То есть не любой объект в массиве - наследник. Там пытаются сказать, что если в массиве есть наследники - то условие выполнено.
Однако эта фраза написана не тем комму следует писать НТД. Потому что фраза:
если массив содержит объекты наследующего класса.
говорит о том что массив должен содержать 2 и более объектов. А для того чтобы быть НТД фразой она должна бы выглядеть как-то так:
В частности, указатель на базовый класс не может быть использован для адресной арифметики если массив содержит по крайней мере один объект наследующего класса среди объектов базового класса.
То есть, это логика. Откуда она у программиста не говорящего по человечески?
Кстати об английском языке. Вот пословица (она не единственная в своём роде, но подходит к случаю) :
monkey sees, - monkey does
Это стало паттерном для мэйнстрим программирования.
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
08.01.2020, 01:43
IGPIGP, твой поток сознания неиссякаем.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
08.01.2020, 03:24
GoshaRubi, вот так и живём. Вот ещё вариант. Особо извращённый. Класс обёртка не понадобился в данном разе. Но не пропадать же добру. Шаблон не слишком сокращает код поскольку написан для конкретных прототипов методов - void(void)... Но всё равно чуть проще чем перегружать всё и вся вручную:
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
using namespace std;
 
struct Base
{
 
    virtual void vf(){cout<<"Base\n";}
    virtual void vf1(){cout<<"Base1\n";}
    virtual ~Base(){}
};
 
struct Derived :public Base
{
    void vf(){cout<<"Derived\n";}
     void vf1(){cout<<"Derived1\n";}
    int a=123;
    int get_a(){return a;}
    ~Derived(){};
};
 
struct arrayWrapper
{
    arrayWrapper(Derived ** pderived, size_t size)
    :m_pderived(pderived), m_size(size)
    {}
 
   Base * operator [](size_t ind)
    {
       return m_pderived[ind] ;
    }
 
    Derived **m_pderived;
    size_t m_size;
};
 
template <class T>
void foo(T arrayPtrBase, size_t n)
{
 for(size_t i=0; i<n; ++i)arrayPtrBase[i]->vf();
}
 
template <
class T,
class ArrElemType,
void (ArrElemType::*fn)()  >
void fun(T arrayPtrBase, size_t n)
{
 for(size_t i=0; i<n; ++i)(arrayPtrBase[i]->*fn)();
}
 
int main()
{
Base base, *pbase=&base;
Derived der1, der2, *pder1=&der1, *pder2=&der2;
Base *ar_bas[]={pbase, pbase,  pbase};
Base *ar_bas_mix[]={pbase, pder1,  pder2};
Derived *ar_der[]={pder1,  pder2, pder1,  pder2};
 
 
arrayWrapper arwr(ar_der, sizeof(ar_der)/sizeof(Derived *));
 
//без обёртки шаблон ест нормально тоже
foo(ar_der, sizeof(ar_der)/sizeof(Derived *));
cout<<endl;
foo(arwr, arwr.m_size);
cout<<endl;
foo(ar_bas, sizeof(ar_bas)/sizeof(Base *));
cout<<endl;
foo(ar_bas_mix, sizeof(ar_bas_mix)/sizeof(Base *));
cout<<endl;
//ужасный синтаксис
//когда смотришь на указатели на члены
//кажется что члены указывают в ответ...
cout<<"\nA teper - gorbatiy!\n"<<endl;
fun<decltype(ar_bas_mix), Base, &Base::vf>
(ar_bas_mix,  sizeof(ar_bas_mix)/sizeof(Base *));
cout<<endl;
fun<decltype(ar_bas_mix), Base, &Base::vf1>
(ar_bas_mix,  sizeof(ar_bas_mix)/sizeof(Base *));
 
return 0;
}
0
285 / 176 / 21
Регистрация: 16.02.2018
Сообщений: 666
08.01.2020, 23:14
Цитата Сообщение от zayats80888 Посмотреть сообщение
в книге Programming: Principles and Practice Using C++ Страуструп проделывает такой же фокус(глава 25.4), и никакой проверки (reinterpret_cast<base**>(0) + 1) == reinterpret_cast<base**>(reinterpret_cas t<der**>(0) + 1)(ну или как там можно это проверить и вообще можно ли) не делает
Он предполагает одинаковый размер у всех указателей в 25.4.4 ("All arrays of pointers have the same layout (independently of what kinds of objects they point to), so we don’t get into the layout problem from §25.4.2")
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.01.2020, 23:14

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

Восходящее и нисходящее преобразование (Upcasting and Downcasting)
Посоветуйте литературу по данному вопросу в разрезе С++ ну или простыми словами что это, для чего нужно заранее спасибо

Неявное восходящее преобразование при защищенном/закрытом наследовании
Здравствуйте. Читаю книгу Стивена Прата по C++. Попался непонятный момент: в одной таблице (в таблице 14.1 в 6-й рус. редакции на стр....

Как сложить объект базового класса с объектом производного(наследуемого класса)
Как умножить объект базового класса с объектом производного(наследуемого класса): ozenka - объект базового класса, а ves- производного ...

Почему объект производного класса не видит префиксный оператор из базового класса?
Короче создал я базовый класс с перегруженным префиксным оператором ++. Потом чтоб его затюнинговать, сделал ему производный класс с...


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

Или воспользуйтесь поиском по форуму:
115
Ответ Создать тему
Новые блоги и статьи
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru