Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.63/35: Рейтинг темы: голосов - 35, средняя оценка - 4.63
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
1

Есть класс A и класс B, класс B вложен в класс A и вложен в него, как классу B получить доступ к переменным класса A просто по имени?

05.07.2011, 22:45. Показов 6883. Ответов 42
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
На самом деле ничё фантастического я не прошу, ведь:
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
template <class T>
class matrix {
        
 friend class diagonal;
 
//Вложенный класс
 public:
  class diagonal; 
 
 //Объявляем переменную такого класса 
 diagonal di;
  
 //Вот эту переменную хотелоь бы изменить в конструкторе вложенного класса
 private: 
  int per; 
 
 
};
 
 
 
template <class T>
class matrix<T>::diagonal {
 public:
  diagonal (){
   //Не изменяеится, говорится что неизвестное использование нестатической переменной per
   per= 90;
  }
};
 
 
int main () {
 matrix <int> k;
 k.di; 
}
Вот посмотрите, по-хорошему надо указать какому именно объекту дружественен класс B, чтобы потом использовать per так:
C++
1
ima_obekta_matrix.per= 90;
Но в том-то и дело, что компилятору уже известно, что объект, членом которого является di, не какой-то мифический объект, а он кокретно тот объект- куда вложен объект di. Но как компилятру объяснить, что переменную per надо брать именнно оттуда? Вот в чём вопрос!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.07.2011, 22:45
Ответы с готовыми решениями:

Может ли объемлющий класс иметь неограниченный доступ к элементам вложенного класса? А вложенный класс — к элементам объемлющего?
Ответ как бы знаю(нет , да). но наверное я что-то не так понимаю, т.к. примерчик написать не...

Как правильно передавать параметры из класса А в класс С через класс B?
Всем привет! Пишу игру - Морской бой! Есть класс Game. Также есть класс Battlefield (модель поля,...

Класс: как обратиться к методу производного класса через итератор на базовый класс?
Есть абстрактный и два порожденных. Хочу создать например list&lt;Base*&gt; list1; затем добавляю себе...

Наследование. Каким образом через ссылку на класс-родитель можно получить доступ к классу-потомку?
&quot;Ведь по ссылке на объект базового класса можно обращаться к объекту производного класса, т.е. к...

42
Заблокирован
05.07.2011, 23:02 2
Теоретически, родитель может научить своего ребёнка знанию о том, где он, родитель, живёт.

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

Сделать можно... но...

Но в вашем случае это же совершенно не нужно, это пример чудовищной архитектуры.
Почему вы постоянно норовите все сделать шиворот-навыворот?

Вы осознаете к каким последствием может привести подобная методика кодирования?
Это мина замедленного действия, вы один паршивый класс реализовать не можете.
А что говорить о системе из классов?

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

Подобная методика написания классов - нарушение всех базовых принципов ООП, главный из которых - инкапсуляуия данных.

/зы необходимость задействовать френдов - хороший повод ещё раз проанализировать архитектуру.

/ззы указатель this спасёт отца русской демократии.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
05.07.2011, 23:11  [ТС] 3
Я ба рад не использовать friend, но: класс B должен получить доступ к полям класса A. Всё. (Да, и если бы можно было сделать класс B производным от A, я бы сделал. Но нельзя- это между прочим.)
А Вашему умению компилить в уме я завидую, но иногда оно даёт сбой.

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
template <class T>
class matrix {
        
 friend class diagonal;
 
 public:
  class diagonal; 
 
 diagonal di;
  
  private: 
  int per; 
 
 
};
 
 
 
template <class T>
class matrix<T>::diagonal {
 public:
  diagonal (matrix& m){
   this->per= 90;
  }
};
 
 
int main () {
 matrix <int> k;
 k.di; 
}
не компилится

Добавлено через 1 минуту
И это... Родитель- ребёнок, я такую терминологию использую обычно если говорю об именно производных и родительских классх. Тут же ими и нге пахнет. Извините.
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
05.07.2011, 23:19 4
стоп...для начала, а зачем конструктору диагонали передавать матрицу?
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
05.07.2011, 23:24  [ТС] 5
Обратимся к вещам, нежели обращаться к их названиям, вот:

0
Заблокирован
05.07.2011, 23:27 6
Цитата Сообщение от kravam Посмотреть сообщение
Я ба рад не использовать friend, но: класс B должен получить доступ к полям класса A. Всё. (Да, и если бы можно было сделать класс B производным от A, я бы сделал. Но нельзя- это между прочим.)
А Вашему умению компилить в уме я завидую, но иногда оно даёт сбой.
Есть правила, ставшие уже классическими для ООП. Описываются практически в любой книге (рекомендую Макконелла. Он здорово мазги прочищает).

Два из них гласят:

1. Все данные-члены класса должны быть закрыты ДЛЯ ВСЕХ других классов. Только класс-
владелец имеет право прямого доступа к своим данным-членам. Если отойти от этого правила,
это может привести к проблемам. (что за проблемы, и с чем связанно хорошо объясняет
Макконелл)

2. Программируйте в терминах интерфейса класса. Это значит, что все действия над объектом
класса производятся исключительно через интерфейс класса. Так, только так, и никак иначе.


А теперь объясните мне, на кой чорт ребёнку иметь прямой доступ к данным-членам родителя?
Почему ребёнок не может обратится к родителю через его интерфейс????

Замечание про компиляцию не вразумел.


Цитата Сообщение от kravam Посмотреть сообщение
И это... Родитель- ребёнок, я такую терминологию использую обычно если говорю об именно производных и родительских классх. Тут же ими и нге пахнет. Извините.
Это уже из области терминологии.

Лично я называю систему-полиморф "семейством", а её членов так и называю "члены семейства". Ну или "родственники одного семейства".

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


Порожденная сущность - ребёнок, порождающая сущность - родитель.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
05.07.2011, 23:44  [ТС] 7
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
template <class T>
class A {
        
 friend class B;
 
 public:
  class B; 
 
 B b;
  
 private: 
  int per; 
 
 
};
 
 
 
template <class T>
class A<T>::B {
 public:
  B (A& m){
   per= 90;
  }
};
 
 
int main () {
 A <int> a;
 a.b; 
}
Добавлено через 5 минут
Цитата Сообщение от Bers Посмотреть сообщение
А теперь объясните мне, на кой чорт ребёнку иметь прямой доступ к данным-членам родителя?
Почему ребёнок не может обратится к родителю через его интерфейс????
Весело с вами
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
template <class T>
class A {
        
 friend class B;
 
 public:
  class B; 
 
 T& set_per () {return per;};
 
 B b;
  
 private: 
  int per; 
 
 
 
};
 
 
 
template <class T>
class A<T>::B {
 public:
  B (A& m){
   set_per ()= 90;  
  }
};
 
 
int main () {
 A <int> a;
 a.b; 
}
Добавлено через 9 минут
Впрочем, даже если бы последнее и сработало, вопрос- почему прямой доступ на сработал? остался бы открытым. Дружественный класс есть дружественный класс, знаете ли.
0
Заблокирован
05.07.2011, 23:57 8
я рекомендую вам в корне изменить подход к проектированию.
Вот лично я это делаю так:

0. Определение предназначения класса. Важно четко понимать, на кой черт он вообще нужен.
1. Продумываю дизайн кода. То бишь, как я вижу использование будущего класса.
Например:

C++
1
2
  CMatrix myMatrix(стартовые арг);
  myMatrix.Work();  //объект выполняет то, ради чего он собственно и был создан.
3. Только теперь я начинаю размышлять о том, какого будит внутреннее устройство класса.
Какие вспомогательные классы он будит использовать, и тп.

Предположим, я пришёл к мнению, что мой класс CMatrix должен использовать
вспомогательный класс CDiagonal. Ну вот так мне захотелось!

Что из этого следует? Из этого следует, что класс CMatrix уже должен знать о существовании
класса CDiagonal. То бишь, CDiagonal уже должен быть спроектирован и создан, причём -
отдельно от CMatrix. CDiagonal ничего не знает ни о каких матрицах, и знание это ему для его
собственной работы не нужно! Это называется "разделение ответственности между классами"

Таким образом получается, что сначала проектируется и собирается класс CDiagonal.
И только потом собирается класс матрицы. Внутри неё объявляется класс диагонали с
красивым именем, ну и матрица может использовать интерфейс диагонали. Но не наоборот.
Диагональ оказывается глубоко запрятанной в матрице, а пользователю матрицы в принципе
даже знать не обязательно о том, что прячеццо в недрах Матрицы.

/зы бывают специфические ситуации, когда ребёнку нужно знать о существовании родителя, но это уже совсем отдельный разговор, опять таки, для таких ситуаций есть свои красивые решения.
Это не ваш случай.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
06.07.2011, 00:33  [ТС] 9
Это я всё знаю, Да, знаю. Просто мне необходимо было сделать класс diagonal не отдельно от matrix, а встроенным в него. И поскольку я чувствую недоверие к собственным решениям, придётся объяснить и это, мне это надо было чтобы программировать так:

C++
1
2
matrix m;
m.diagonal_ [2][3]= 99;
Всё, третьему элементу второй диагонали присваивается значение 99. Всё просто. А вся эта бодяга из-за того началась, что я не хочу хранить диагонали как массив векторов, а хочу использовать хитрую формулу, которая переводила бы диагональные координаты в матричные.

То есть тут сперва одна перегрузка [] срабатывает, потом другая [], в результате последней должна вызваться функция:
f_perevod_kkoordinat(koordinati* koordinati_, 2, 3) (обратите внимание на аргументы)

Так, эта функция исходя из диагональных координат 2, 3 (вторая диагональ, третий элемент) заполнит структурку
C++
1
2
3
strucr koordinati {
 int x; int y;
}
где x- номер строки, y- номер столбца матрицы, после чего вызывается:
C++
1
T& get_element_matritsi (x, y);
/////////////////////////////////////////////////////////////////////////////////

Проще можно сделать так,такой интерфейс
1)[CPP]m.diagonal_ (2, 3)= 99;/CPP]
угу? Но мне охота по другому. Классический синтаксис чтобы был!

2)Или можно было скропать массив диагоналей, а потом перегрузить оператор [], получив адрес вектора, а потом взять его элемент. И это бы я сделал. Но я массив диагоналей кропать не хочу, а хочу использьвать изящную формулку (я её уже наваял) перевода диагональных координат в стандартные матричные.

И вообще тяжело в ученье легко в бою, упражнения должны быть трудны, иначе грош им цена. Ну и конечно, реалистичны, но о последнем я судит не могу, ибо их сам придумываю, а потом разбираюсь, а реализуемы ли они вообще ли нет.

Добавлено через 6 минут
Кстати, я с самого начала исхожу из интерфейса, наверное, это неправильно?

Добавлено через 1 минуту
Ну то есть вы исходите из функциональности класса, я в принципе тоже но ещё исхожу и чтобы был простой интерфейс, вот и парюсь.
0
Заблокирован
06.07.2011, 00:49 10
Цитата Сообщение от kravam Посмотреть сообщение
Кстати, я с самого начала исхожу из интерфейса, наверное, это неправильно?
Я понимаю слово "интерфейс", как "способ управления".
И я всегда прежде всего думаю об интерфейсе. Мне очень критично, что бы пользоваться классом было легко, удобно).

Единственное, когда я размышляю об интерфейсе управления некой сущности, я называю её не "классом", а "инструментом". Потому что я такой подход использую не только при разработке одного класса, но и целой системы (библиотеки/ етс)

И уже определившись с дизайном интерфейса, я под него придумываю собственно реализацию.

Смысл прост - нужно что бы наружу торчал только интерфейс, а все остальное - упрятано внутри. Инкапсуляция, понимаешь... )
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
06.07.2011, 00:51  [ТС] 11
Вот я так и делаю. В общем, моя задача из разряда нерешаемых. Жаль, очень жаль.
0
Заблокирован
06.07.2011, 01:00 12
Цитата Сообщение от kravam Посмотреть сообщение
matrix m;
m.diagonal_ [2][3]= 99;

Тут понимаете в чем деликатность то... внешне смотрится, как многомерный массив. А на самом деле он им является, или нет? Это может сбить с толку. А все, что сбивает с толку - источник ошибок.

Лично я вообще избегаю многомерных массивов.
Интерфейс должен быть очивиден. Интуитивно понятен.

И ещё один момент: запись типа Array[x][y] можно понять, как:
Array[столбец][строка], а можно и наоборот: Array[строка][столбец]

Даже если знаешь точно - перепутать ничайно очень просто.
Это.... не читабельно.

Добавлено через 2 минуты
Цитата Сообщение от kravam Посмотреть сообщение
Вот я так и делаю. В общем, моя задача из разряда нерешаемых. Жаль, очень жаль.
В с++ все решаемо. Не решаемо окажется позже, когда вы захотите добавить ешё какую нить фичу в класс матрицы))

Научить ребёнка знать, где живёт его родитель можно - например, с помощью указателя this
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
06.07.2011, 01:12  [ТС] 13
Вы меня удивляете. Давайте всё же условимся, что Array[x][y] это Array[строка][столбец], всё остальное от лукавого. По крайней мере, если чел, пользующийся моим классом или я сам перепутает строку со столбцом, значит тут я ничё поделать не смогу.

Опять же Array[x][y] Это такой массив векторов:
int
int int
int int int
int int
int

диагонали то есть. Да это не двумерный массив.(куцый какой-то) Но не всё ли равно, что он на самом деле? Важно, чтобы можно было просто обратиться к какому-нибудь его элементу простым способом. (Может, я много на себя беру, но для меня такой способ m.diagonal_ [2][3]= 99 и есть интуитивно понятный) Инкапсуляция, знает ли...
Но это лирика всё.
....................................

А на счёт this я так и не понял, вот же:
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
template <class T>
class A {
        
 friend class B;
 
 public:
  class B; 
 
 T& set_per () {return per;};
 
 B b;
  
 private: 
  int per; 
 
 
 
};
 
 
 
template <class T>
class A<T>::B {
 public:
  B (){
   this->set_per ()= 90;  
  }
};
 
 
int main () {
 A <int> a;
 a.b; 
}
0
Заблокирован
06.07.2011, 01:29 14
тогда, если исходить из дизайна интерфейса, почему бы не сделать вот так:

CMatrix myMatrix(строк, столбцов); //вот так мы создаём объект

Value = myMatrix [x][y]; //вот так мы получаем доступ к элементу

myMatrix[x][y] = Value; //а вот так элементу матрицы присваивается значение.
0
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
06.07.2011, 01:46  [ТС] 15
С этим проблем нет, всё работает кроме указаннного
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
matrix<int> y (6, 7);
 
//Рандомно инициализирую
y.init_rand (1, 100);
 
//Вывожу  матрицу
y.vivod();
 
 //Доступ к отдельному элементу
printf ("%d\n", y[3][4]);  
 
//А это я его изменяю
 y[3][4]= 99;
 
 
//А вот тут проблемы и решить их можно либо y.diagonal(1, 2) либо найдя ответ на поставленный //вопрос
//Тут я начал работать с диагональю, y.diagonal[2][1] соответствет y[2][0];
y.diagonal[2][1];
0
Заблокирован
06.07.2011, 02:09 16
kravam, приучайтесь давать красивые, красноречивые имена функциям, переменным, и тп.

А то не понятно, как этот код читать.

Цитата Сообщение от kravam Посмотреть сообщение
y.diagonal[2][1];
Что должно происходить в этой строчке?
0
187 / 174 / 18
Регистрация: 22.03.2010
Сообщений: 612
06.07.2011, 06:42 17
Есть класс A и класс B, класс B вложен в класс A и вложен в него, как классу B получить доступ к переменным класса A просто по имени?
доступ можно получить только к статическим объектам
можно сделать так
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
template <class T>
class matrix {
 
 friend class diagonal;
 
//Вложенный класс
 public:
 
  class diagonal;
 
 //Объявляем переменную такого класса
 diagonal di;
 
 //Вот эту переменную хотелоь бы изменить в конструкторе вложенного класса
 private:
  static int per;
 
 
};
 
template <class T> int matrix<T>::per = 50;
 
 
template <class T>
class matrix<T>::diagonal {
 public:
  diagonal (){
   //Не изменяеится, говорится что неизвестное использование нестатической переменной per
      per= 90;
  }
};
 
 
int main()
{
 
 
     matrix <int> k;
 
 
}
Цитата Сообщение от kravam Посмотреть сообщение
this->set_per ()= 90;
странная конструкция, учитывая, что this типа B*, а у В* нету никакого set_per
как вариант также можно сделать функцию статической
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
template <class T>
class matrix {
 
 friend class diagonal;
 
//Вложенный класс
 public:
    static T& set_per () {return per;};
  class diagonal;
 
 //Объявляем переменную такого класса
 diagonal di;
 
 //Вот эту переменную хотелоь бы изменить в конструкторе вложенного класса
 private:
  static int per;
 
 
};
 
template <class T> int matrix<T>::per = 50;
 
 
template <class T>
class matrix<T>::diagonal {
 public:
  diagonal (){
       set_per ()= 90;
  }
};
 
 
int main()
{
 
 
     matrix <int> k;
 
 
}
p.s. fasked в твоей предыдущей теме вроде объяснил, что между вложенными классами нет никакой взаимосвязи, которую ты пытаешься провести в своих примерах. По сути класс, в который что-то вкладывают работает как пространство имён и никак иначе. То что ты пытаешься здесь замутить, можно сделать с помощью наследования, либо с помощью статических объектов

Добавлено через 4 минуты
есть вложенный класс который является другом объемлюющего и всё это должно компилиться.
Цитата Сообщение от fasked Посмотреть сообщение
Вложенность позволяет ограничить "область действия" класса.
вот наиболее важная мысля
0
Заблокирован
06.07.2011, 11:18 18
Цитата Сообщение от pito211 Посмотреть сообщение
доступ можно получить только к статическим объектам
У статических функций и данных внутри класса есть свои специфические задачи.

Если предполагается, что доступ к интерфейсу класса должен осуществляться только через интерфейс объекта класса, то статик-функции не нужны.

Если предполагается, что все данные-члены класса должны быть уникальны для каждого объекта класса, то статик-данные не нужны.
0
187 / 174 / 18
Регистрация: 22.03.2010
Сообщений: 612
06.07.2011, 11:41 19
Есть класс A и класс B, класс B вложен в класс A и вложен в него, как классу B получить доступ к переменным класса A просто по имени
требованиям автора статические данные и методы полностью удовлетворяют.
наследование удовлетворяет требованиям из поста #13
0
Заблокирован
06.07.2011, 11:57 20
Цитата Сообщение от pito211 Посмотреть сообщение
требованиям автора статические данные и методы полностью удовлетворяют.
наследование удовлетворяет требованиям из поста #13
Да это разве требования... так набросок предварительный.
От задачи плясать нужно.

А к чему вы наследование упомянули?

Добавлено через 4 минуты
краеугольным камнем во всей этой истории является вот такая конструктива:

y.diagonal[2][1]; // не понятно что происходит в этой строчке.

Если это действительно то, что я думаю (деталь интерфейса), то становится ясно, что задумал автор, и как это реализовать.
Если это то, что я думаю, то тут не нужны ни статики, ни наследование.
Подождём автора)
0
06.07.2011, 11:57
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.07.2011, 11:57
Помогаю со студенческими работами здесь

Класс таблиц баз данных и класс записей в таблице(реляционная таблица). Предусмотреть класс связей между таблицами
Здравствуйте! Никак не могу продумать структуру этой программы. Проходим наследование, но я все...

Класс: Описать класс Points, затем производный от него Circle
Задание: Описать класс Points, затем производный от него Circle. Создать динамический массив...

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

3 класса. Родительский класс - класс животных. Два класса наследника: Гиппопотамы и Зебры. Выбор структуры данных
Добрый День. Есть задача. Есть 3 класса. Родительский класс - это класс животных. Он абстрактный и...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru