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

Работа с абстрактным классом

07.01.2016, 21:42. Показов 1842. Ответов 34
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!
Имеется небольшой класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <irrlicht.h>
 
class EngineInit
{
public:
    IrrlichtDevice* device = 0;
    ISceneManager* smgr = 0;
    IVideoDriver* driver = 0;
    IGUIEnvironment* guienv = 0;
 
    ILightSceneNode* sun;
    vector3df pos;
 
    int initialise();
};
C++
1
2
3
4
5
int EngineInit::initialiseEngine()
{
    driver = device->getVideoDriver();
    guienv = device->getGUIEnvironment();
}
Выдает сегфолт на driver = device->getVideoDriver(). Известно, что классы IrrlichtDevice и далее -- абстрактные. Я прекрасно понимаю, что пишу программу неправильно.
Если же исключить ООП и писать реализацию напрямую в функции main, то проблемы не наблюдается.
Как нужно исправить программу, чтобы не получать сегфолт?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.01.2016, 21:42
Ответы с готовыми решениями:

Полиморфизм с абстрактным классом
Добрий день, нуждаюсь в помощи. У меня есть абстрактный класс IStudent_Manip и производный класс Student_Manipulator. Хочу сделать...

Непонятки с абстрактным классом
У нуба возник вопрос :) Вот объявляю я абстрактный Inline класс. Ну под инлайн я имею ввиду, что он без cpp, реализация в H. #pragma...

Ошибка при работе с абстрактным классом pair
Всем доброго времени суток, стоит задача создать абстрактный класс pair и создать от него производный класс complex, определив при этом...

34
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
07.01.2016, 22:34
Ну изначально-то в device нолик. Неудивительно, что при обращении к нему сегфолты возникают. А надо откуда-то взять указатель на полноценный объект. Как-то он должен в Irrlicht создаваться.
0
51 / 51 / 8
Регистрация: 31.10.2012
Сообщений: 481
07.01.2016, 22:57  [ТС]
Nick Alte, нолик -- ясное дело. Если, например, без классов я напишу так:
C++
1
2
3
4
5
6
IrrlichtDevice* device = 0;
IVideoDriver* driver = 0;
int main ()
{
driver = device->getVideoDriver ();
}
... то все будет прекрасно.
0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
08.01.2016, 07:27
Цитата Сообщение от SanchezPluz Посмотреть сообщение
... то все будет прекрасно.
Нет, не будет. Будет всё тот же сегфолт.

Гугление официального сайта Irrlicht, переход в туториалы, из них первый - Hello World, общее время меньше минуты. Видим следующее:
C++
1
IrrlichtDevice *device = createDevice( video::EDT_SOFTWARE, dimension2d<u32>(640, 480), 16, false, false, false, 0);
Ведь просто же всё, зачем заниматься ерундой?
1
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
08.01.2016, 09:45
Цитата Сообщение от SanchezPluz Посмотреть сообщение
... то все будет прекрасно.
Не будет и быть не может.
0
51 / 51 / 8
Регистрация: 31.10.2012
Сообщений: 481
08.01.2016, 10:27  [ТС]
Nick Alte, я уроки уже по десять раз прокурил, в очередной нового ничего не открою.
Просто по своей невнимательности не учел, что эта строка должна идти первой. Вопрос закрыт.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
08.01.2016, 11:13
Цитата Сообщение от Nick Alte Посмотреть сообщение
Нет, не будет. Будет всё тот же сегфолт.
Не будет, 0 просто передается как this в метод, если внутри метода не происходит обращения к членам, то все пройдет гладко.

Не по теме:

Хотя на днях как раз на форуме было высказано мнение, что это UB, но не уверен. Думаю тут не С++ стандарт курить надо, а что нибудь типа x86 abi, лень разбираться. Опираясь на мои знания это вроде не UB на x86.

0
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
08.01.2016, 13:28
Цитата Сообщение от Kastaneda Посмотреть сообщение
на форуме было высказано мнение, что это UB, но не уверен
Если бы не обращался, то таки UB.

Вот только конкретно этот метод вполне себе обращается и вполне ожидаемо сегфолтит.
0
08.01.2016, 13:37

Не по теме:

Цитата Сообщение от Nick Alte Посмотреть сообщение
Если бы не обращался, то таки UB.
Ну вообще thiscall (и позднее конвенции для x86_64) нам говорит, что разыменования не будет, С++ стандарт говорит, что запись ptr-> идентична (*ptr).. Нужно для себя решить кто из них сильнее :) На уровне языка может и UB, но мне кажется т.к. thiscall тут перетягивает одеяло на себя, то можно считать что все вполне definded.
Хотя если забыть об архитектуре и говорить только терминами языка, то да, может UB.

0
50 / 49 / 10
Регистрация: 24.01.2010
Сообщений: 225
08.01.2016, 19:37
опс...
не досмотр
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
08.01.2016, 23:38
Цитата Сообщение от Kastaneda Посмотреть сообщение
Ну вообще thiscall (и позднее конвенции для x86_64) нам говорит, что разыменования не будет
нет, не говорит.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
09.01.2016, 07:31
Цитата Сообщение от hoggy Посмотреть сообщение
нет, не говорит.
скажем так - оно не говорит, что разыменование будет.

Добавлено через 8 минут

Не по теме:

Полез гуглить что-нибудь на эту тему, интересную вещь нашел

/* объясняют что NULL передается как this, бла бла бла */
Microsoft's MFC function GetSafeHwnd actually relies on this behavior. I don't know what they were smoking.
реально GetSafeHwnd допускает вызов через null pointer

0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.01.2016, 10:11

Не по теме:

Цитата Сообщение от Kastaneda Посмотреть сообщение
реально GetSafeHwnd допускает вызов через null pointer
это не показательно.
разработчики платформы запросто используют
не корректные с точки зрения стандарта ходы.

C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
 
struct example
{
    int m;
};
 
int main()
{
    std::cout << "hello, world!\n";
    std::cout << offsetof(example, m) << std::endl;
}
stddef.h
C++
1
2
3
4
5
#ifdef _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) )
#else  /* _WIN64 */
#define offsetof(s,m)   (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
#endif  /* _WIN64 */
обычно, всякого рода гнусные хаки слетают при оптимизациях.
здесь же, как мы видим, квалификатор volatile запрещает компилятору
оптимизировать конструкцию.

однако, от этого UB не перестает быть UB.
и не стоит им уподобляться.

эти ребята не просто знают тонкости своего компилятора,
но и умеют заставить его по особенному
собирать код своих библиотек.

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

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

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

студийная реализация завязалась на баге в Visual Studio 7.1
(автоматический id времени компиляции)
после исправления которого,
лососнула тунца вплоть до выхода delctype

в том, что касается MFC - есть ряд драконовских ограничений.
например, связанные с множественным наследованием:

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
#include <iostream>
 
struct msvc
{
    bool is_valid()const { return this ? true : false; }
};
 
struct trololo
{
    int m = 33;
};
 
// при множественном наследовании
// первым всегда должен идти майкросотовский стафф
struct app: trololo, msvc {};
 
int main()
{
    std::cout << "hello, world!\n";
 
    app* p = nullptr;
 
        //что бы не получилась вот такая жёпь
    std::cout << "is valid? (must be 0) " << p->is_valid() << '\n';
}
и ещё вагон и тележка дыр в безопасности.

или вот код:
C++
1
2
3
4
5
    auto* p = GetDlgItem(IDC_ANIMATE2);
    assert(p && "IDC_ANIMATE1 not exist");
 
    CAnimateCtrl* anim 
        = static_cast<CAnimateCtrl*>(p);
в доке описаны случаи когда приведение допустимо, и даже рекомендуемо
однако, технически, это - сумасшедший каст теплого к мягкому.

работая с MFC, нужно быть оч аккуратным,
и внимательно читать доки.



Добавлено через 12 минут
Цитата Сообщение от Kastaneda Посмотреть сообщение
скажем так - оно не говорит, что разыменование будет.
оно вообще никаким боком не касается того,
какой путь пришлось пройти аргументам,
что бы оказаться на стеке функции.

единственная компетенция соглашения о вызове:
как упакованы аргументы по итогу.

и кстати, компиляторы при оптимизациях имеют полное право
покласть на это соглашение с большим прибором.


компиляторы закладываются, что код не содержит UB,
а значит всякие засранцы не будут писать такой код:
(последний пример)
Static члены класса

а значит можно сэкономить,
пробросив аргументы как нибудь через регистры,
а не стек.

"честный" thiscall будет, только если там элипсис, или volatile,
или какие нибудь волшебные слова компилятора:
Как гарантировать передачу единственного параметра через стек?
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
09.01.2016, 14:43
Цитата Сообщение от hoggy Посмотреть сообщение
C++
1
2
//что бы не получилась вот такая жёпь
* * std::cout << "is valid? (must be 0) " << p->is_valid() << '\n';
не понял что не так с этим кодом?

Добавлено через 4 минуты
касательно
C++
1
0 -> func();
здесь и в соседней теме я пытался донести, что несмотря на то, что стандарт С++ говорит нам, что это UB в данном конкретном случае (вызов ф-ции члена) мы знаем как оно реально работает на x86 и можем смело ожидать, что разыменования не будет. Это не оптимизация, это вполне логичное поведение компилятора.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.01.2016, 17:22
Цитата Сообщение от Kastaneda Посмотреть сообщение
не понял что не так с этим кодом?
вернет 1, очевидно жеж.

Добавлено через 51 секунду
Цитата Сообщение от Kastaneda Посмотреть сообщение
что разыменования не будет
будет.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
09.01.2016, 17:29
Цитата Сообщение от hoggy Посмотреть сообщение
будет.
спор бессмысленый, я говорю не будет, ты говоришь будет.

Цитата Сообщение от hoggy Посмотреть сообщение
вернет 1, очевидно жеж.
Это фишка MFC или что? Там какой-то свой метакомпилятор типа как в qt?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.01.2016, 17:35
Цитата Сообщение от Kastaneda Посмотреть сообщение
спор бессмысленый, я говорю не будет, ты говоришь будет.
не я. стандарт.

Цитата Сообщение от Kastaneda Посмотреть сообщение
Это фишка MFC или что?
это фишка с++.

я малость поспешил.
вот правильная иллюстрация:

http://rextester.com/OSFPG49584

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
#include <iostream>
 
struct msvc
{
    bool is_valid()const { return this ? true : false; }
    
    int v=999;
};
 
struct trololo
{
    int m = 33;
};
 
// при множественном наследовании
// первым всегда должен идти майкросотовский стафф
struct app: trololo, msvc {};
 
int main()
{
    std::cout << "hello, world!\n";
 
    app* p = nullptr;
 
        //что бы не получилась вот такая жёпь
    std::cout << "is valid? (must be 0) " << p->is_valid() << '\n';
}
выводит 1.

потому что указатель p совпадает с началом подобъекта trololo.
в то время, как подобъект msvc отстоит от начала объекта на некоторое смещение,
определяемое данными-членами и выравниванием.

когда нужно запустить метод is_valid,
то обращение идет к подобъекту msvc,
компилятор автоматически выполняет корректировку смещения.
поэтому нулевое p не совпадает с this подобъекта msvc.
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
09.01.2016, 17:48
Цитата Сообщение от hoggy Посмотреть сообщение
не я. стандарт.
но разыменования не происходит при включении в комплияторе строго следования стандарту.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.01.2016, 19:10
Цитата Сообщение от Kastaneda Посмотреть сообщение
но разыменования не происходит при включении в комплияторе строго следования стандарту.
происходит.
0
10.01.2016, 17:13

Не по теме:

hoggy, не хочу приводить рабочий пример и ассемблерный выхлоп потому что:
- я знаю, что ты можешь получить это без меня
- я знаю, что ты и так знаешь результат

посему дальнейший спор считаю абсолютно бессмысленным.

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.01.2016, 17:13
Помогаю со студенческими работами здесь

Создать иерархию наследования с абстрактным базовым классом
Доброго времени суток! Помогите, пожалуйста, сделать: 2) Создать абстрактный базовый класс с виртуальной функцией &quot;Площадь&quot;....

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

работа с классом
пишу класс быстрой математики (знаю что многие делали в инете дофига всего, но всё же) сделал таблицу корней в общем то всё работает...

Работа с классом
Необходимо написать класс который будет переводить из 16-ой системы счисления числа в 10-ю систему счисления, классы только неделю назад...

работа с классом
Напсал код: #include &lt;IOSTREAM&gt; #include &lt;fstream&gt; #include &quot;rus.h&quot; #include &quot;work.h&quot; using namespace std; class Temperatura ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера 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. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru