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

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

20.02.2019, 17:26. Показов 1473. Ответов 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
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 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
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 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
33371 / 21497 / 8234
Регистрация: 22.10.2011
Сообщений: 36,893
Записей в блоге: 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
1703 / 899 / 207
Регистрация: 25.11.2009
Сообщений: 1,848
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
1703 / 899 / 207
Регистрация: 25.11.2009
Сообщений: 1,848
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
Ответ Создать тему
Новые блоги и статьи
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru