Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Шаблоны и дружественность 
:(
    Опции темы
Nastya
Дата 27.7.2005, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 27.3.2002
Где: Мариуполь

Репутация: 5
Всего: 44



Есть шаблон класса, как в другом классе объявить, что ему будут дружественны все классы поражденные от шаблона


--------------------
Что бы понять рекурсию, надо понять рекурсию

"Профессионал - это человек сделавший все возможные ошибки в очень узкой области". Н.Бор
PM MAIL   Вверх
oper54
Дата 27.7.2005, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 217
Регистрация: 13.5.2005

Репутация: 1
Всего: 1



Помоему никак....
PM MAIL   Вверх
Earnest
Дата 27.7.2005, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Точно никак - потому что шаблоны с разными параметрами порождают совершенно разные, с точки зрения компилятора, типы. Так что твоя задача звучит примерно так: как сделать дружественными кучу типов, которую я в данный момент перечислить точно не могу.
Решение в этом случае одно - просто объявить все, что нужно, public или выделить public часть в отдельный классс. Public значительно лучше, чем friend, т.к. friend полностью и неуправляемым образом нарушает инкапсуляцию. И использовать его лучше пореже - примерно как goto. Обойтись без friend можно ВСЕГДА, только часто ВЛОМ. Но это уже совершенно другая проблема.






--------------------
...
PM   Вверх
ManiaK
Дата 27.7.2005, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Homo Sapience
***


Профиль
Группа: Комодератор
Сообщений: 1145
Регистрация: 3.8.2004
Где: ИУ5-93

Репутация: 5
Всего: 29



Цитата(Earnest @ 27.7.2005, 21:26)
Обойтись без friend можно ВСЕГДА, только часто ВЛОМ.

Хорошо сказала smile Не люблю friend.
PM MAIL WWW   Вверх
LPBOY
Дата 31.7.2005, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



Цитата(Nastya @ 27.7.2005, 13:25)
Есть шаблон класса, как в другом классе объявить, что ему будут дружественны все классы поражденные от шаблона


Код

class A{
template <typename T> friend class B;
//...
};

template <typename T>
class B{
//...
};


Вот тестик:

Код

#include <iostream>
#include <conio.h>

using namespace std;

class A{
template <typename T> friend class B;
public:
    A():i(65){}
private:
        int i;
};

template <typename T>
class B{
public:
    B(){}
    void f(){std::cout<<a.i;}
private:
    A a;
};

int main()
{
    B<int> b;
    b.f();
    getch();
    return 0;
}



Цитата(Earnest @ 27.7.2005, 20:26)
Public значительно лучше, чем friend, т.к. friend полностью и неуправляемым образом нарушает инкапсуляцию.

А public не нарушает инкапсуляцию?

Цитата(ManiaK @ 27.7.2005, 21:33)
Не люблю friend


И чем вам всем этот friend не угодил smile
ИМХО, полезная вещь если правильно использовать.

Это сообщение отредактировал(а) LPBOY - 31.7.2005, 20:15
--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
LPBOY
Дата 31.7.2005, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



Цитата(Nastya @ 27.7.2005, 13:25)
Есть шаблон класса, как в другом классе объявить, что ему будут дружественны все классы поражденные от шаблона


А если ты имела в виду, что оба класса шаблоны, тогда так:

Код

#include <iostream>
#include <conio.h>

using namespace std;

template<typename T>
class A{
template <typename T> friend class B;
public:
    A():i(65){}
private:
        int i;
};

template <typename T>
class B{
public:
    B(){}
    void f(){std::cout<<a.i;}
private:
    A<T> a;
};

int main()
{
    B<int> b;
    b.f();
    getch();
    return 0;
}

--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
ManiaK
Дата 1.8.2005, 08:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Homo Sapience
***


Профиль
Группа: Комодератор
Сообщений: 1145
Регистрация: 3.8.2004
Где: ИУ5-93

Репутация: 5
Всего: 29



Цитата(LPBOY @ 31.7.2005, 16:33)
ИМХО, полезная вещь если правильно использовать.

Использовать дружбу это как носить всё своё состояние в нагрудном кармане: рано или поздно нарвёшься smile
Шой-то меня сегодня потянуло на сравнения...
PM MAIL WWW   Вверх
Nastya
Дата 1.8.2005, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 27.3.2002
Где: Мариуполь

Репутация: 5
Всего: 44



Я имела в виду как раз обычный класс, а ему дружественный именно шаблон. Спасибо. Ответ оказался простым и логичным smile


--------------------
Что бы понять рекурсию, надо понять рекурсию

"Профессионал - это человек сделавший все возможные ошибки в очень узкой области". Н.Бор
PM MAIL   Вверх
Earnest
Дата 2.8.2005, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(LPBOY @ 31.7.2005, 15:33)
А public не нарушает инкапсуляцию?

Public не нарушет, а управляет. Если вы видите в чужом коде public - все ясно. Если private - делаю, что хочу, могу даже функции как Inline в cpp-файле писать - я ведь полностью определяю, что где лежит. А вот стоит добавить friend - все, никаких гарантий, т.к. friend имеет доступ ко всем кишкам. Поэтому friend можно использовать только в пределах интерфейса класса. Т.е. делать друзьями, скажем, глобальную функцию, тесно связанную с данным классом или какой-то вспомогательный класс, объявленный в том же h-файле. Хотя функцию лучше уж сделать статической и объявить в классе. Вспомогательный класс тоже лучше вложить, и тогда пусть дружат. Насчет объявления глобальных функций друзьями, единственный вариант, когда альтернативы дружбе нет - это перегрузка операторов.

Пример вредности дружбы. Допустим, есть какой-нибудь довольно навороченный класс, с закрытыми данными и неполным интерфейсом (ну не написали сразу, считая, что будут решать проблемы по мере их поступления). В какой-то момент из другого места программы потребовался к нему доступ, причем нужных интерфейсных методов нет. Программист, не долго думая, вместо того, чтобы добавить/изменить интерфейс класса, просто добавляет строчку "friend class XXX". Все довольны, все работает, все быстро сделано. Потом еще один урод делает тоже самое, уже для своего класса... В итоге, через несколько лет, когда приходит светлая мысль, что тот самый класс данных не соответствует текущему моменту и неплохо бы его переписать, выясняется, что в друзьях у него уже полпрограммы и все это придется перелопачивать... Кончается это обычно тем, что от переписывания отказываются (слишком долго и неизвестно еще чем кончится), добавляют очередной костыль, и программа хромает дальше.
Это, конечно, крайний случай, но подобные варианты в реальном коде встречаются куда чаще, чем хотелось бы.
Вывод - используйте "friend" только в крайнем случае, и только для тесно связанных функций или классов.
Хотя пример LPBOY очень интересный (с синтаксической точки зрения). Не знала, что так можно.


--------------------
...
PM   Вверх
LPBOY
Дата 2.8.2005, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 228
Регистрация: 12.7.2005

Репутация: 20
Всего: 20



Когда я прочитал

Цитата(Earnest @ 27.7.2005, 20:26)
Решение в этом случае одно - просто объявить все, что нужно, public


то подумал, что вместо

Код

class A{
template <typename T> friend class B;
//...
private:
int member1;
float member2;
};


предлагается

Код

class A{
//...
public:
int member1;
float member2;
};


Видимо ты все-таки имела в виду поместить в public соответствующие функции.

Цитата(Earnest @ 2.8.2005, 18:29)
Пример вредности дружбы...

Ну... неправильно использовать можно не только дружбу ;)
Можно еще public, private и т.д.))
--------------------
Каждый человек по-своему прав, а по-моему нет...
PM MAIL   Вверх
Earnest
Дата 3.8.2005, 07:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



LPBOY, разумеется... все что угодно можно использовать неправильно. Просто friend ИМХО опаснее, чем public. Этот как GOTO - вполне нормальный оператор и никто не мешает с его помощью писать хорошо структурированный код - писали же люди во времена фортрана. Но покажите мне новичка, который GOTO пользуется правильно. А так как без него вполне можно обойтись, отцы C++ и не рекомендуют его использовать.
Точно так же и friend. Иногда он очень помогает (я уже писала), но только при аккуратном применении. А у новичка вызывает сильное искушение решать им все проблемы. А правила обращения с public-private и пр. гораздо проще объяснить.

Пример, с которого началась тема, не иллюстрирует, ИМХО, правильное применение friend.


--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0717 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.