Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
4 / 4 / 4
Регистрация: 21.04.2014
Сообщений: 139

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

21.06.2014, 19:11. Показов 1847. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Мне бы хотелось узнать в чем ошибка моего кода

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void __fastcall TForm1::Button1Click( TObject * Sender )
{
    int pointer = ( int ) & Form1->Edit1;
 
    pointer = pointer +sizeof( TEdit * ); // Получаю адрес указателя на второе поле
 
    if ( pointer == ( int ) & Form1->Edit2 )
    {
        // Этот код выполняется
        TEdit * p = ( TEdit * )pointer;
        ShowMessage( p->Text );  // После выполнения этой команды происходит ошибка памяти
    }
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.06.2014, 19:11
Ответы с готовыми решениями:

Как получить доступ к элементам массива работая с ним как с указателем и адресной арифметикой
int array = { {1,2,3}, {1,2},{1,2,3,4}, {1,2,3,4},{1,2,},}; for(int i = 0; i < 25; i++) printf("%d ", array); ...

Конструктор копирования для класса с указателем на абстрактный класс
Всем привет. Как реализовать конструктор копирования для класса Foo? class Base { public: ... ...

В чем разница между указателем и указателем на указатель?
int x, *p, *q; x=10; p=&x; q=p; cout<<*q; int x, *p, **q; x=10; p=&x; q=&p;

10
 Аватар для uhx
60 / 60 / 19
Регистрация: 11.07.2013
Сообщений: 305
21.06.2014, 21:29
Цитата Сообщение от A_N_A_N_A_S Посмотреть сообщение
Спасибо большое но мне бы хотелось узнать в чем ошибка моего кода
Может потому что он неверный?
sizeof(TEdit*) - не факт что ты попадешь на следующий эдит.
Память динамическая, соотв. Эдиты могут быть разных размеров.

Добавлено через 14 секунд
Без указателя на конкретный участок памяти - никак
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
22.06.2014, 11:47
Цитата Сообщение от uhx Посмотреть сообщение
Память динамическая, соотв. Эдиты могут быть разных размеров.
Без указателя на конкретный участок памяти - никак
Эдиты разных размеров быть не могут. Все экземпляры класса TEdit занимают одинаковое количество памяти.

A_N_A_N_A_S, твоя ошибка в предположении, что с полями класса можно без заморочек работать, как с массивом. Это не совсем так, хотя и возможно. Любой класс и в самом деле представлен в памяти, как структура со всеми данными класса подряд, но в данном случае есть проблемы - класс формы содержит сотни полей данных, большая часть из которых унаследована, плюс указатель на таблицу виртуальных функций, но это уже детали. Поэтому указатели на твои эдиты будут находится в самом конце области памяти, выделенной под данные класса формы. Короче, кнопочку, что ты написал, для достижения результата придется тыкать много-много раз. Полюбопытствуй.
Это так, лирическое отступление. На самом деле пользоваться таким подходом для тебя нет причин. Есть множество более простых путей, один из которых и был представлен D1973.
2
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
24.06.2014, 14:16
Лучший ответ Сообщение было отмечено BRcr как решение

Решение

Цитата Сообщение от A_N_A_N_A_S Посмотреть сообщение
Получаю адрес указателя на второе поле
"Получаю адрес указателя на область памяти, которую в дальнейшем пытаюсь интерпретировать как второе поле".

Цитата Сообщение от A_N_A_N_A_S Посмотреть сообщение
в чем ошибка моего кода
Если более конкретизироваться нежели BRcr, и говорить непосредственно про ваш код, то их собственно три:
1) Где гарантии того, что второй эдит расположен в памяти позже первого? (куда его аллокатор положит, там он и будет)
2) Где гарантии того, что сместив указатель, вы не выйдете за границы выделенной вашей программе памяти? (что скорее всего и произошло)
3) Где гарантии того, что нарезая всю память программы по размеру одного эдита, вам не попадется что-то меньшее/большее, что сместит чтение так, что, когда вам все же попадется требуемый эдит, от него обрежется лишь часть? (это если забегать вперед к циклу)

Нарисую свою любимую картинку. Давно я в них не упражнялся:


P.S. Вот, еще может быть интересно: Создать 8-мерный массив
2
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
24.06.2014, 19:50
Лучший ответ Сообщение было отмечено BRcr как решение

Решение

Раз пошла такая пьянка, я поэкспериментировал и вывел способ обойти все, указанные камрадом SatanaXIII, сложности.
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
#include <signal.h>
 
void SignalHandler( int signal )
{
    throw "av";
}
 
// ---------------------------------------------------------------------------
void __fastcall TForm1::btn1Click( TObject * Sender )
{
    TEdit * edit;
    TMemo * memo;
    double exceptions_count( 0 );
    typedef void( *SignalHandlerPointer )( int );
    SignalHandlerPointer previousHandler;
 
    previousHandler = signal( SIGSEGV, SignalHandler );
 
    for ( TComponent * ptr( Form1 ), *ptr_limit( Form1 + ( sizeof( TForm1 ) ) );
        ptr < ptr_limit;
        ptr = ( TComponent * )( ( ( char * )ptr ) + 1 ) )
    {
        try
        {
            if ( edit = dynamic_cast < TEdit * > ( ptr ) )
            {
                edit->Text = "found " + edit->Name;
            }
            if ( memo = dynamic_cast < TMemo * > ( ptr ) )
            {
                memo->Text = "found " + memo->Name;
            }
        }
        catch ( ... )
        {
            ++exceptions_count;
        }
    }
    signal( SIGSEGV, previousHandler );
    ShowMessage( "Скушано " + FloatToStr( exceptions_count ) + " исключений ))" );
}
Работает с задержкой в 5-10 секунд, наверно из-за количества dynamic_cast'ов и проглоченных исключений.
Миниатюры
Получить определенные поля класса, работая с указателем на класс, как с указателем на массив  
1
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
25.06.2014, 09:18
Цитата Сообщение от BRcr Посмотреть сообщение
Работает с задержкой в 5-10 секунд
На моей микро ЭВМ пару минут. Х)
Миниатюры
Получить определенные поля класса, работая с указателем на класс, как с указателем на массив  
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
25.06.2014, 20:33
Не, неправильно я написал. sizeof( TForm1 ) возвращает 960 байт, а значит, предыдущий код сканирует память еще почти на мегабайт за область класса.
Правильно было бы вот так:
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
void SignalHandler( int signal )
{
    throw "av";
}
// ---------------------------------------------------------------------------
 
void __fastcall TForm1::btn_goClick( TObject * Sender )
{
    TEdit * edit;
    TMemo * memo;
    double exceptions_count( 0 );
    typedef void( *SignalHandlerPointer )( int );
    SignalHandlerPointer previousHandler;
 
    previousHandler = signal( SIGSEGV, SignalHandler );
 
    for ( BYTE * ptr( ( BYTE * )Form1 ), *ptr_limit( ( BYTE * )( Form1 + 1 ) );
        ptr < ptr_limit;
        ++ptr )
    {
        try
        {
            if ( edit = dynamic_cast < TEdit * > ( ( TComponent * ) ptr ) )
            {
                edit->Text = "found " + edit->Name;
            }
            if ( memo = dynamic_cast < TMemo * > ( ( TComponent * ) ptr ) )
            {
                memo->Text = "found " + memo->Name;
            }
        }
        catch ( ... )
        {
            ++exceptions_count;
        }
    }
    signal( SIGSEGV, previousHandler );
    ShowMessage( "Скушано " + FloatToStr( exceptions_count ) + " исключений ))" );
}
Так сканируются именно 960 байт класса формы... но ничего не находит. Причем количество исключений av на несколько десятков меньше 960 - то есть dynamic_cast все-таки получает указатели, с которых может вытянуть RTTI, но это не эдиты...

Если чуток расширить область:
C++
1
*ptr_limit( ( BYTE * )( Form1 + 10 ) )
- то находит один из эдитов и\или мемо. Но это в режиме дебага. В режиме релиза, когда в экзешник не включается отладочная информация, ничего не находит и иногда виснет.
Подумал, что это из-за published заморочки хитрые у компилятора с размещением объектов в памяти. Сделал в паблике свой указатель на эдит, инициализировал в конструкторе - один черт не находит его.

Короче, я понял, что ничего я не понял.
0
 Аватар для kodv
1449 / 1121 / 347
Регистрация: 11.04.2011
Сообщений: 2,621
26.06.2014, 05:25
BRcr, Это происходит из-за того, что сканируя память, выделенную под класс, вы получаете адреса не объектов классов TEdit, TMemo и других, а адреса переменных, которые хранят эти адреса. Накидал по-быстрому код (поэтому не столь красиво, как у вас), который сканирует память класса:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        int exCount = 0;
        for(int i = int(Form1); i < int(Form1 + 1); ++i)
                try
                {
                        dynamic_cast<TEdit*>((TObject*)*(int*)i)->Text = "This Edit is Find";
                }
                catch(...)
                {
                        ++exCount;
                }
        ShowMessage("Exception count: " + (AnsiString)exCount);
}
Добавлено через 2 минуты
PS: На форме кнопка и едит. После нажатия кнопки отображается информация о 218 исключениях и надпись в едите "This Edit is Find".
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
26.06.2014, 08:32
Я вообще изначально думал не о конкретной форме, а о сканировании всего приложения.
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
27.06.2014, 19:22
Спасибо kodv. Так все верно работает. Предыдущие коды искали именно сами объекты, размещенные в куче, а не указатели на них. Поэтому при расширении области просмотра их и находило...

Ну, и шлифанем это дело реальным визуальным представлением.


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class TForm1 : public TForm
{
__published: // IDE-managed Components
    TEdit *edit1;
    TEdit *edit2;
    TEdit *edit3;
    TMemo *memo1;
    TButton *btn_go;
    TChart *chrt1;
    TBubbleSeries *bblsrs1;
    void __fastcall btn_goClick(TObject *Sender);
 
public: // User declarations
 
        
     TEdit *edit4;
    __fastcall TForm1( TComponent * Owner );
    // __fastcall ~TForm1( );
} ;
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
__fastcall TForm1::TForm1( TComponent * Owner ) :
    TForm( Owner )
{
     edit4 = new TEdit( this );
     edit4->Parent = this;
     edit4->Visible = true;
     edit4->Name = "edit4";
}
 
// ---------------------------------------------------------------------------
void SignalHandler( int signal )
{
    throw "av";
}
// ---------------------------------------------------------------------------
 
void __fastcall TForm1::btn_goClick( TObject * Sender )
{
    TEdit * edit;
    TMemo * memo;
    double exceptions_count( 0 );
    typedef void( *SignalHandlerPointer )( int );
    SignalHandlerPointer previousHandler;
 
    previousHandler = signal( SIGSEGV, SignalHandler );
 
 
    for ( int i = int( Form1 ); i < int( Form1 + 1 ); ++i )
    {
            bblsrs1->AddBubble( i, 100, 5, "", clBlack );
        try
        {
            if ( edit = dynamic_cast < TEdit * > ( ( TComponent * ) *( int * )i ) )
            {
                edit->Text = "found " + edit->Name;
                bblsrs1->AddBubble( i, 120, 10, edit->Name, clRed );
            }
            if ( memo = dynamic_cast < TMemo * > ( ( TComponent * ) *( int * )i ) )
            {
                memo->Text = "found " + memo->Name;
                bblsrs1->AddBubble( i, 120, 10, memo->Name, clRed );
            }
        }
        catch ( ... )
        {
            ++exceptions_count;
        }
    }
    signal( SIGSEGV, previousHandler );
    ShowMessage( "Скушано " + FloatToStr( exceptions_count ) + " исключений ))" );
}
1
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
01.07.2014, 10:08
Цитата Сообщение от BRcr Посмотреть сообщение
Ну, и шлифанем это дело реальным визуальным представлением
Очень информативный график. Х)
Ну а вообще весело.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
01.07.2014, 10:08
Помогаю со студенческими работами здесь

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

Управление указателем поля
Я слышал, что с помощью JavaScript можно поместить указатель в начало или конец поля для ввода текста, например text area. Но возможно ли...

Переделать функцию c указателем на int, на функцию с указателем на void
Есть рабочий код qsort для int: void qsort(int *base, int n) { // Прекратить если количество элементов меньше либо равно единице....

Как сделать ассоциативный массив с указателем на структуру?
У меня этот код не компилируется #include &lt;map&gt; #include &lt;iostream&gt; struct testStruct { testStruct( int initVal ) { ...

ошибки с указателем на родительский класс
задание: сделать 3 класса: список, стек(списком), очередь(списком). Методы: вывод, добавление, удаление. Использовать при обращении...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение/ Перевод https:/ / **********/ gallery/ thinkpad-x220-tablet-porn-gzoEAjs . . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru