Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648

Разместить экземпляры одного класса в теле другого

20.02.2019, 17:26. Показов 1517. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем здравствуйте.
Есть внешний класс, содержащий массив экземпляров внутренних классов:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Tinner
{
private:
public:
    Tinner()
    {
        a = 0;
        s = "";
    }
    int a;
    SmallString<10> s;
};
 
class Touter
{
private:
public:
    Tinner classInner[16];
}classOuter;
Мне нужно убедиться, что массив экземпляров классов Tinner расположен непосредственно в теле экземпляра класса Touter.
Экземпляр классса Touter в дальнейшем предполагается сохранять/считывать из файла, поэтому в теле класса не должно быть никаких ссылок, только реальные данные. Для того чтобы в этом убедиться я вывожу в метку размер classOuter меняя один из членов класса Tinner.
При SmallString<10> s размер classOuter составил 256 байт
При SmallString<20> s размер classOuter составил 448 байт (прибавилось 192 байта)
При SmallString<30> s размер classOuter составил 576 байт (прибавилось 128 байт)
При SmallString<40> s размер classOuter составил 768 байт (прибавилось 192 байта)
При SmallString<50> s размер classOuter составил 896 байт (прибавилось 128 байт)
Казалось бы размер classOuter должен увеличиваться на одинаковую величину 16*10= 160 байт, но этого не происходит. Почему?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.02.2019, 17:26
Ответы с готовыми решениями:

Не работает вызов одного метода в теле другого
здравствуйте. занимаюсь переводом проекта с С++ на C#. путем &quot;дебага&quot; обозначилась проблема, что в одной из моих функций &quot;private void...

Может ли тело одного цикла частично содержаться в теле другого?
Помогите, пожалуйста, решить пару вопросов 1. .Имеются описания массивов: Type Wektor=array of real; Var A: array of char; ...

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

12
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33411 / 21521 / 8236
Регистрация: 22.10.2011
Сообщений: 36,922
Записей в блоге: 12
20.02.2019, 19:07
Перепроверил. Вот, что получилось:

При SmallString<10> s размер classOuter составил 256 байт
При SmallString<20> s размер classOuter составил 448416 байт (прибавилось 192 байта160 байт)
При SmallString<30> s размер classOuter составил 576 байт (прибавилось 128160 байт)
При SmallString<40> s размер classOuter составил 768736 байт (прибавилось 192 байта160 байт)
При SmallString<50> s размер classOuter составил 896 байт (прибавилось 128160 байт)

Что я делаю не так?
RAD XE4 Win7/WinXP
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
20.02.2019, 19:49  [ТС]
volvo, странно, почему разные "шаги" при одинаковом увеличении байт? Использовалось sizeof(classOuter)?
Но мне главное быть уверенным в том, что если я сохраню classOuter в двоичном файле, а затем считаю из файла в classOuter структура данных не нарушится.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33411 / 21521 / 8236
Регистрация: 22.10.2011
Сообщений: 36,922
Записей в блоге: 12
21.02.2019, 00:03
Лучший ответ Сообщение было отмечено jkrnd как решение

Решение

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

Да, именно sizeof(classOuter) использовался.

Цитата Сообщение от jkrnd Посмотреть сообщение
если я сохраню classOuter в двоичном файле, а затем считаю из файла в classOuter структура данных не нарушится.
Не должна. Посмотри на предка, от которого наследуется SmallString:
C++
1
2
3
4
5
6
  template <unsigned char sz> class SmallStringBase
  {
  protected:
    unsigned char Len;
    char Data[sz];
  };
, просто, как хозяйственное мыло, что тут может нарушиться?
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
22.02.2019, 09:29  [ТС]
volvo, кстати в RAD XE4 тот же результат, что и в BCB6, как на Win8.1x64, так и на XP
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
class Tinner
{
private:
public:
    Tinner()
    {
        a = 0;
        s = "";
    }
    int a;
    SmallString<10> s;
};
 
class Touter
{
private:
public:
    Tinner classInner[16];
}classOuter;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    int a = sizeof(classOuter);
    Label1->Caption = IntToStr(a);
}
Попутный вопрос. Почему XE-4 ругается на
C++
1
Label1->Caption = IntToStr(sizeof(classOuter));
?
0
51 / 39 / 15
Регистрация: 20.09.2018
Сообщений: 163
22.02.2019, 11:06
Цитата Сообщение от jkrnd Посмотреть сообщение
Казалось бы размер classOuter должен увеличиваться на одинаковую величину 16*10= 160 байт, но этого не происходит. Почему?
может виновата фрагментация памяти кратно int или размеру какой-нибудь стандартной минимальной единицы объема оперативки (страница/кластер/блок или что-то подобное) ?
Сталкивался с этим на freeRTOS.
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
22.02.2019, 20:30  [ТС]
RomanSedyshev, я думал об этом, но числа, согласитесь, не такие, каких ожидаешь при выравнивании границ
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33411 / 21521 / 8236
Регистрация: 22.10.2011
Сообщений: 36,922
Записей в блоге: 12
22.02.2019, 21:25
jkrnd, запустил код под BCB6 на Win7 x32, фигня какая-то происходит. Вывожу не только общий размер структуры outerClass, но и размер одного из classInner при этом:

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
class Tinner
{
private:
public:
    Tinner()
    {
        a = 0;
        s = "";
    }
    int a;
    SmallString<10> s;
};
 
class Touter
{
private:
public:
    Tinner classInner[16];
}classOuter;
 
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    ShowMessage(IntToStr(sizeof(classOuter.classInner[0])) + " bytes; " +
                IntToStr(sizeof(classOuter)));
 
}
SmallString<10> -> 16 bytes; 256
SmallString<20> -> 28 bytes; 448
SmallString<30> -> 36 bytes; 576
SmallString<40> -> 48 bytes; 768
SmallString<50> -> 56 bytes; 896

Вот что мне совершенно непонятно - это почему при <10> строка занимает 16 байт, а при <20> - 28. Откуда тут берутся еще 2 байта? Выравнивание - выравниванием, но ведь оно должно быть ОДИНАКОВЫМ, собственно данные занимают на 1 байт больше, чем передано в параметре шаблона, данные однобайтовые, поэтому никаких пустых байт компилятор вставлять не должен. Поле a имеет абсолютно одинаковый тип при всех значениях параметра шаблона, величина выравнивания тоже не изменяется между пересборками, так почему эти 2 байта то добавляются, то убираются? Что за дичь творит компилятор? И главное - почему XE4 на WinXP/Win7 выдает одинаковые приращения и адекватные размеры Tinner?

Попробовал
C++
1
2
3
#pragma pack(push, 1)
// тут описание типов
#pragma pack(pop)
, поведение стало гораздо более адекватным, как и положено размер Tinner перестал быть плавающим, стал строго на 5 байт больше, чем задаваемый размер SmallString. Но почему без подавления выравнивания творится бред?
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
22.02.2019, 21:34  [ТС]
Цитата Сообщение от volvo Посмотреть сообщение
без подавления выравнивания творится бред
вот и я о том же.
На всякий случай применю подавление выравнивания, хотя данные читаются-пишутся из одной и той же программы и вроде всё нормально.
0
 Аватар для Lelik-pahan
1709 / 905 / 207
Регистрация: 25.11.2009
Сообщений: 1,850
22.02.2019, 21:51
volvo, а разве не таким и должно быть поведение, если шаг выравнивания по умолчанию равен 4?
16 делится на четыре, 26 - нет, получаем 28.
1
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
22.02.2019, 21:58  [ТС]
Lelik-pahan, посмотрите пожалуйста самый первый вопрос. Как эту то арифметику объяснить?
0
 Аватар для Lelik-pahan
1709 / 905 / 207
Регистрация: 25.11.2009
Сообщений: 1,850
22.02.2019, 22:14
По той же причине int a /*4 байта*/ + SmallString<10> s /*11 байт*/ равно 16, а не 15.

Цитата Сообщение от jkrnd Посмотреть сообщение
посмотрите пожалуйста самый первый вопрос. Как эту то арифметику объяснить?
сейчас гляну...

Добавлено через 14 минут
Ну так все же сходится. Посмотри размер Tinner во всех 5 случаях. Получается то, что volvo приводил выше.
16, 28, 36, 48 и 56. Умножь это на 16, получается 256, 448, 576, 768 и 896 соответственно.

А такие размеры Tinner получаются потому, что размер самих данных меняется с шагом в 10 байт, а выравнивание по умолчанию 4 байта, т. е. размер класса изменяется на шаг кратный 4.
2
 Аватар для jkrnd
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
22.02.2019, 22:28  [ТС]
Lelik-pahan, кажется дошло. Спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.02.2019, 22:28
Помогаю со студенческими работами здесь

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

Передача значения переменной из метода одного класса в метод другого класса
Добрый вечер! Есть основная форма Form1 в которой есть метод private void button1_Click(object sender, EventArgs e) обрабатывающий...

Из одного класса обратиться к свойству progressBar из другого класса (основного окна)
Привет! :) Помогите пожалуйста нубу (мне). У меня есть два класса. Первый (основной), его код: namespace CMS { ///...

Перегрузка операции + с преобразованием объектов одного класса в объекты другого класса
Доброго времени суток! Изучаю ООП, при выполнении следующего задания возникли сложности: Создать класс Polar для хранения полярных...

С помощью делегата из одного класса вызвать private метод с другого класса
доброго времени суток. такой вопрос. С применением делегатов и пониманием проблем нет когда происходит простой вызов из Main() функции. Но...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Контроль корректности заполнения дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru