Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.91
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
#1

Может ли объект-член, или объект-элемент достучаться к содержащему его? - C++

14.03.2014, 09:27. Просмотров 1513. Ответов 58
Метки нет (Все метки)

Предположим,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A
{
 ...
};
class B
{
 ....
 A a;
...
};
class C
{
 ...
 A *a;
 ...
}
...
B b1;
B *b2;
C c;
size_t i;
...
. Может ли b1.a достучаться до b1, b2[i].a к b2[i], а c.a[i] - до c? Данные по c.a и b2 могут перемещаться reallocом.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.03.2014, 09:27     Может ли объект-член, или объект-элемент достучаться к содержащему его?
Посмотрите здесь:

Если объект константный, означает ли это, что ни один его член-элемент или член-метод не изменится? - C++
Назрел такой вопрос: Если объект константный это означает, что ни один его член-элемент или член-метод не изменится или только некоторые из...

Может ли функция иметь аргументом другую функцию или объект? - C++
Внимание тупой вопрос )) А может ли функция иметь аргументом другую функцию или объект?

Реализовать двухсвязный список. Каждый элемент списка может содержать один объект - C++
Здравствуйте, мне нужно было реализовать двухсвязный список. Каждый элемент списка может содержать один объект. Объект может быть трех...

при вызове конструктора присваивания надо возвращать ссыль на объект или сам объект. Смысл? Значения нужных полей меняютмся и без этого! - C++
Друзья! Обнаружил пробел в знаниях. Собсно, вопрос в теме. Дополню лишь: поля объекта меняются на нужные значения и безо всякого возврата...

Как достать объект-контейнер, а не его элемент - C++
Добрый вечер всем. Возник вопрос. Я читал Страуструпа и на одной из его глав, есть упражнение по созданию класса-контейнера, в...

Объект osteram& или как его вывести в переменную ? - C++
Здравствуйте Объект osteram& или как его вывести в переменную ? cin... cout... printf... scanf А вот как же вывети поток...

Указатель на объект из указателя на член класса - C++
Что как-то сей вопрос ставит меня в тупик. class A { int i; } obj; int main()

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.03.2014, 13:35  [ТС]     Может ли объект-член, или объект-элемент достучаться к содержащему его? #16
Цитата Сообщение от DrOffset Посмотреть сообщение
class A;
class Aa
{
public:
* * Aa(A & parent) : parent_(parent) {}
private:
* * A & parent_;
};
class Ab
{
public:
* * Ab(A & parent) : parent_(parent) {}
private:
* * A & parent_;
};
class A
{
public:
* * A() : a(*this), b(*this) {}
private:
* * friend class Aa; // для полного доступа. Можно убрать, если он не нужен.
* * friend class Ab;
Aa a;
* * Ab b;
};
, ейси.
C++
1
b2=(B*) reaaloc((void*)b2, NeCount);
, адреса агрегирующих объектов могут в этот момент поменяться.
aLarman
642 / 563 / 89
Регистрация: 13.12.2012
Сообщений: 2,109
14.03.2014, 13:39     Может ли объект-член, или объект-элемент достучаться к содержащему его? #17
realloc вроде копирует, не должны, вот только тогда в агрегирующем классе могут слететь ссылки на агрегированные объекты
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.03.2014, 13:40  [ТС]     Может ли объект-член, или объект-элемент достучаться к содержащему его? #18
Цитата Сообщение от DrOffset Посмотреть сообщение
Стоит заметить ,что у этого есть свои ограничения. Например, в конструкторах и деструкторах таких классов нельзя обращаться к данным родителя. Т.к. они могут быть либо еще не созданы, либо уже уничтожены. Собственно поэтому подобная фича не доступна по умолчанию.
Уже инициализируется агрегированный объект, а агрегирующего ещё нет. Очень интересно. Или для агрегированный ещё не удалялся, а агрегирующий уже удалён. Также весело.

Добавлено через 1 минуту
Цитата Сообщение от aLarman Посмотреть сообщение
realloc вроде копирует, не должны, вот только тогда в агрегирующем классе могут слететь ссылки на агрегированные объекты
Какого они слетят? Все внутриобъектные смещения константы в пределах класса.
DrOffset
7058 / 4199 / 949
Регистрация: 30.01.2014
Сообщений: 6,965
14.03.2014, 14:08     Может ли объект-член, или объект-элемент достучаться к содержащему его? #19
Цитата Сообщение от taras atavin Посмотреть сообщение
адреса агрегирующих объектов могут в этот момент поменяться.
Чтобы этого не происходило надо пользоваться С++ средствами для перераспределения памяти, которые вызовут соответствующие деструкторы, соответствующие конструкторы копирования и т.д. Либо реализовывать это поверх realloc самостоятельно. realloc в чистом виде не годится для любых сложны C++ классов, а не только в этом случае.

Добавлено через 9 минут
taras atavin,
Посмотри на досуге вот этот пример
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 <vector>
#include <cstdio>
 
class MyTest
{
public:
    MyTest()               {  printf("%s\n", __PRETTY_FUNCTION__); }
    MyTest(MyTest const &) {  printf("%s\n", __PRETTY_FUNCTION__); }
    ~MyTest()              {  printf("%s\n", __PRETTY_FUNCTION__); }
};
 
int main()
{
    std::vector<MyTest> myTest;
    myTest.reserve(1);
 
    myTest.push_back(MyTest());
    puts("------");
    myTest.push_back(MyTest());
    puts("------");
    myTest.push_back(MyTest());
    puts("------");
}
если хранить приведенный мной выше класс в таком контейнере, то рассогласования ссылок внутри объектов никогда не произодет. Т.к. будут гарантированно вызваны все конструкторы и деструкторы.
А вот копировать с помощью, например, memcpy не-POD типы в С++ в принципе не очень хорошая идея.
Alex5
1048 / 711 / 104
Регистрация: 12.04.2010
Сообщений: 1,789
14.03.2014, 17:25     Может ли объект-член, или объект-элемент достучаться к содержащему его? #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
24
25
26
27
28
29
30
31
32
33
34
35
struct B
{
    void* func();
};
 
struct A
{
    int m; 
    int n;
    B b1;
    B b2;
};
 
void* B::func()
{
    B A::* q; // указатель на член класса ( член, имеющий тип B )
    q = &A::b1; //  0x00000008
 
    int* pInt2 = reinterpret_cast<int*>( &q ); // *pInt2 == 8 , т.е. sizeof(A::m) + sizeof(A::n)
 
    // чтобы получить адрес объекта-агрегата, из this вычитаем 8
    void* parent = reinterpret_cast<char*>(this) - *pInt2;
    return parent;
}
 
int main()
{
    A a;
    cout << "\n &a    " << &a << endl;
 
    void* p = a.b1.func();
    cout << "\n result of  a.b1.func()  " << p << endl;
 
    // ... 
}
Миниатюры
Может ли объект-член, или объект-элемент достучаться к содержащему его?  
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.03.2014, 17:34  [ТС]     Может ли объект-член, или объект-элемент достучаться к содержащему его? #21
Цитата Сообщение от Alex5 Посмотреть сообщение
B A::* q; // указатель на член класса ( член, имеющий тип B )
* * q = &A::b1; // *0x00000008
Это что за синтаксис такой?
DrOffset
7058 / 4199 / 949
Регистрация: 30.01.2014
Сообщений: 6,965
14.03.2014, 17:43     Может ли объект-член, или объект-элемент достучаться к содержащему его? #22
taras atavin, обычный для указателей на члены класса. Это по сути как раз те самые смещения. Поэтому их получают через определение класса
&A::b1
, не через объект.
А вот reinterpret_cast в этом случае - нехорошо. Пример не учитывает выравнивание, к тому же компилятор для не standard-layout классов может менять местами поля в целях оптимизации. Ну и достаточно просто добавить в такой класс еще одно поле и не провести соответствующих изменений в коде доступа к полям, то все смещения "поплывут".
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.03.2014, 17:45  [ТС]     Может ли объект-член, или объект-элемент достучаться к содержащему его? #23
Цитата Сообщение от DrOffset Посмотреть сообщение
taras atavin, обычный для указателей на члены класса. Это по сути как раз те самые смещения. Поэтому их получают через определение класса
&A::b1
, не через объект.
Расшифруй как для нуба в кубе.
DrOffset
7058 / 4199 / 949
Регистрация: 30.01.2014
Сообщений: 6,965
14.03.2014, 18:04     Может ли объект-член, или объект-элемент достучаться к содержащему его? #24
taras atavin,
Есть объект типа А. Назовем его obj.
У него естественно есть адрес.
Адрес есть и у каждого его поля. Указатель на это поле можно получить двумя способами. Первый способ - это получить указатель на объект поля.
C++
1
int * pA = &obj.a;
А можно (второй способ) получить смещение относительно базы.
C++
1
int A::* offsetA = &A::a;
Ну вот такая запись, она означает, что мы взяли относительный указатель на поле типа int в классе А.
Для доступа по этому смещению нам нужна база. Это базой может служить непосредственно объект типа А.
C++
1
2
A obj;
int v = (obj.*offsetA);
тут мы получили значение поля а, смещение которого мы запомнили в offsetA, у объекта obj.
либо, можно использовать для этого указатель:
C++
1
2
A * pObj;
int v = (pObj->*offsetA);
Для указатель на методы те же правила. Только в отличие от данных, нельзя получить абсолютный адрес метода, только вот такой относительный.
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.03.2014, 18:07  [ТС]     Может ли объект-член, или объект-элемент достучаться к содержащему его? #25
Нда. А кто мешает юзать имена полей и поручить смещения компилятору?
DrOffset
7058 / 4199 / 949
Регистрация: 30.01.2014
Сообщений: 6,965
14.03.2014, 18:14     Может ли объект-член, или объект-элемент достучаться к содержащему его? #26
taras atavin, никто. Просто иногда это бывает полезно.

Добавлено через 6 минут
Лично я не находил применения таким указателям на данные. Но зато использовал указатели на методы (у них синтаксис похож, только параметры еще добавляются). Это полезно при реализации делегатов.
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
14.03.2014, 18:23  [ТС]     Может ли объект-член, или объект-элемент достучаться к содержащему его? #27
Цитата Сообщение от Alex5 Посмотреть сообщение
B A::* q; // указатель на член класса ( член, имеющий тип B )
* * q = &A::b1; // *0x00000008
int* pInt2 = reinterpret_cast<int*>( &q ); // *pInt2 == 8 , т.е. sizeof(A::m) + sizeof(A::n)
// чтобы получить адрес объекта-агрегата, из this вычитаем 8
* * void* parent = reinterpret_cast<char*>(this) - *pInt2;
* * return parent;
А откуда известно, что this указывает именно на b1? Что выведет:
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
struct B
{
    void* func();
};
 
struct A
{
    int m; 
    int n;
    B b1;
    B b2;
};
 
void* B::func()
{
    B A::* q; // указатель на член класса ( член, имеющий тип B )
    q = &A::b1; //  0x00000008
 
    int* pInt2 = reinterpret_cast<int*>( &q ); // *pInt2 == 8 , т.е. sizeof(A::m) + sizeof(A::n)
 
    // чтобы получить адрес объекта-агрегата, из this вычитаем 8
    void* parent = reinterpret_cast<char*>(this) - *pInt2;
    return parent;
}
 
int main()
{
    A a;
    cout << "\n &a    " << &a << endl;
 
    void* p = a.b2.func();
    cout << "\n result of  a.b2.func()  " << p << endl;
 
    // ... 
}
? А ведь по условию функцией может владеть даже элемент динамического массива.
Alex5
1048 / 711 / 104
Регистрация: 12.04.2010
Сообщений: 1,789
14.03.2014, 20:18     Может ли объект-член, или объект-элемент достучаться к содержащему его? #28
Цитата Сообщение от DrOffset Посмотреть сообщение
Пример не учитывает выравнивание, к тому же компилятор для не standard-layout классов может менять местами поля в целях оптимизации.
Данный пример как раз учитывает выравнивание.
Цитата Сообщение от DrOffset Посмотреть сообщение
Ну и достаточно просто добавить в такой класс еще одно поле ...
Давайте посмотрим.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
/* добавим поле char, больше никаких изменений в коде нет (см. сообщение #20) */
struct A
{
    char c; 
    // ... 
};
/* Результат: 
 
 &a    0019F9EC
 
 result of  a.b1.func()  0019F9EC
 
*/
Цитата Сообщение от DrOffset Посмотреть сообщение
А вот reinterpret_cast в этом случае - нехорошо
Это верно, но по другой причине. А именно, указатель на член класса определяет смещение поля объекта.
Но вряд ли можно полагаться на то, что он просто равен смещению. Зависимость может быть какой-то другой.
(Вариант 1. Указатель на член класса равен смещению+1. Значение 0 зарезервируем для недействительного указателя.)
(Вариант 2. Указатель на член класса равен смещению. Недействительный указатель: 0xFFFFFFFF.)
(Другие варианты ... )
Так что, если использовать .* или ->* компилятор всё расшифрует правильно. А при использовании reinterpret_cast возникнет ошибка.
DrOffset
7058 / 4199 / 949
Регистрация: 30.01.2014
Сообщений: 6,965
14.03.2014, 23:29     Может ли объект-член, или объект-элемент достучаться к содержащему его? #29
Цитата Сообщение от Alex5 Посмотреть сообщение
Данный пример как раз учитывает выравнивание.
В принципе было бы достаточно этой фразы. Действительно, учитывает. А "магическая" константа была в комментарии, а не в коде, на что я и не обратил внимания
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.03.2014, 07:37     Может ли объект-член, или объект-элемент достучаться к содержащему его?
Еще ссылки по теме:

компилятор считает объект l-value, но объект таковым не является - C++
итак есть базовый абстрактный класс Дерево, есть два его наследника Плодовое Дерево и Лесное Дерево. Также существует класс Контейнер...

Один объект не может дополнить другой - C++
Есть два объекта,принадлежащие этому классу. #include &quot;value_class.h&quot; class Variable { private: ...

Указатель объект на объект (фикс ошибки) - C++
/*Есть некий объект ObjectOne который содержит в private: такую строку*/ ObjectTwo *obj = new ObjectTwo(); /*При выводе на экран...

Объект удаляется до возвращения его из функции - C++
Есть следующий код перегрузки операции &quot;+&quot; для сложения матриц: Matrix operator+(const Matrix &amp;x) { Matrix result(*this); ...

Как объявить объект класса, не создавая его? - C++
Нужно объявить объект класса, но чтобы при этом не вызывался конструктор? Просто потом хочу его создать через конструктор копирования....


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

Или воспользуйтесь поиском по форуму:
taras atavin
Ушёл с форума.
3569 / 1752 / 91
Регистрация: 24.11.2009
Сообщений: 27,619
15.03.2014, 07:37  [ТС]     Может ли объект-член, или объект-элемент достучаться к содержащему его? #30
Данный пример не учитывает, что однотипных членов может быть несколько.
Yandex
Объявления
15.03.2014, 07:37     Может ли объект-член, или объект-элемент достучаться к содержащему его?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru