Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 25, средняя оценка - 4.72
kravam
быдлокодер
1702 / 889 / 45
Регистрация: 04.06.2008
Сообщений: 5,499
#1

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

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

На самом деле ничё фантастического я не прошу, ведь:
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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.07.2011, 22:45
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Есть класс A и класс B, класс B вложен в класс A и вложен в него, как классу B получить доступ к переменным класса A просто по имени? (C++):

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

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

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

Создать класс “Автомагазин”, состоящей из класса ”Марки машин”. Класс “Автомагазин ”:название магазина, адрес, телефон. Класс “ Марки машин ”: марка - C++
Создать класс “Автомагазин”, состоящей из класса ”Марки машин”. Класс “Автомагазин ”:название магазина, адрес, телефон. Класс “ Марки...

Отдельно класс данных, класс формул и главный класс - C++
Здравствуйте! У меня есть три вопроса. Первый вопрос. Скажите пожалуйста! Правильный ли это подход к созданию приложений :...

Определить класс-строку. В класс включить два конструктора: для определения класса строки строкой символов и п - C++
Определить класс-строку. В класс включить два конструктора: для определения класса строки строкой символов и путем копирования другой...

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

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

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

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

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

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

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

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

/ззы указатель this спасёт отца русской демократии.
0
kravam
быдлокодер
1702 / 889 / 45
Регистрация: 04.06.2008
Сообщений: 5,499
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
Jupiter
Каратель
Эксперт С++
6560 / 3981 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
05.07.2011, 23:19 #4
стоп...для начала, а зачем конструктору диагонали передавать матрицу?
0
kravam
быдлокодер
1702 / 889 / 45
Регистрация: 04.06.2008
Сообщений: 5,499
05.07.2011, 23:24  [ТС] #5
Обратимся к вещам, нежели обращаться к их названиям, вот:

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

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

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

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


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

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


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

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

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


Порожденная сущность - ребёнок, порождающая сущность - родитель.
0
kravam
быдлокодер
1702 / 889 / 45
Регистрация: 04.06.2008
Сообщений: 5,499
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
Bers
Заблокирован
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
kravam
быдлокодер
1702 / 889 / 45
Регистрация: 04.06.2008
Сообщений: 5,499
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
Bers
Заблокирован
06.07.2011, 00:49 #10
Цитата Сообщение от kravam Посмотреть сообщение
Кстати, я с самого начала исхожу из интерфейса, наверное, это неправильно?
Я понимаю слово "интерфейс", как "способ управления".
И я всегда прежде всего думаю об интерфейсе. Мне очень критично, что бы пользоваться классом было легко, удобно).

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

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

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

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

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

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

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

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

Научить ребёнка знать, где живёт его родитель можно - например, с помощью указателя this
0
kravam
быдлокодер
1702 / 889 / 45
Регистрация: 04.06.2008
Сообщений: 5,499
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
Bers
Заблокирован
06.07.2011, 01:29 #14
тогда, если исходить из дизайна интерфейса, почему бы не сделать вот так:

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

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

myMatrix[x][y] = Value; //а вот так элементу матрицы присваивается значение.
0
kravam
быдлокодер
1702 / 889 / 45
Регистрация: 04.06.2008
Сообщений: 5,499
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, 01:46
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.07.2011, 01:46
Привет! Вот еще темы с ответами:

Создайте класс, в котором есть ostream& operator<<. Класс должен содержать очередь с приоритетом - C++
Создайте класс, в котором есть ostream&amp; operator&lt;&lt;. Класс должен содержать очередь с приоритетом. Создайте генератор — заполнитель очереди...

Как преобразовать указатель на класс к указателю на асбтрактный класс? - C++
Но тут есть одна тонкость- два промежуточных класса. Вот код, надеюсь всё из него понятно. #include &lt;stdio.h&gt; ...

Как создать класс со вложенной структурой указателей на класс? - C++
В классе Concept хранится массив (точнее map) структур Rel. Сама же структура Rel должна содержать указатели на класс Concept. ...

Разработать производный от абстрактного класса Figure класс и класс, производный от производного - C++
Разработать базовый абстрактный класс Figure с пустым виртуальным методом print для вывода в дальнейшем полной информации об объекте: ...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

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