Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > функции, поинтеры, классы.....


Автор: sgrey 25.12.2007, 20:03
смотрел одну из имплементаций бинарного дерева и в коде нашёл такую вещь

Код

typedef void (*FunctionType)(TreeItemType& anItem);

используется это дело в функциях
Код

void preorder(TreeNode *treePtr, FunctionType visit)
{...
visit(treePtr->item
...};

я так понимаю что первая запись - это способ передать функцию как параметр в функцию... такие вопросы:
1) Зачем поинтер к типу функции?
2) Для работы с данными класса можно написать внутренний метод - зачем так изголяться? какие преимущества?
3) Как это дело работает? как мне в функцию FunctionType добавить функциональность? например - удалить посещаемый элемент....

далее, имеется такая функция
Код

destroytree(TreeNode *& treePtr)

зачем поинтер и ссылка вместе? разве только передача поинтера не даёт нам тойже, даже большей функциональности как и передача ссылки ?

заранее спасибо! )

Автор: zkv 25.12.2007, 20:23
Цитата(sgrey @  25.12.2007,  20:03 Найти цитируемый пост)
Зачем поинтер к типу функции?

чтобы можно было передать любую функцию с такой сигнатурой
Цитата(sgrey @  25.12.2007,  20:03 Найти цитируемый пост)
Для работы с данными класса можно написать внутренний метод - зачем так изголяться? какие преимущества?

не понятен вопрос
Цитата(sgrey @  25.12.2007,  20:03 Найти цитируемый пост)
Как это дело работает? как мне в функцию FunctionType добавить функциональность? например - удалить посещаемый элемент....

FunctionType - это тип а не функция, ты можешь определить свою функцию:
Код

void ViewItem(TreeItemType& anItem)//это функция типа FunctionType
{
   anItem.Print();
}

и передать ее в функцию preorder, а он (этот preorder) ее применит (а может нет - без реализации нельзя сказать) для некоторых элементов.
Цитата(sgrey @  25.12.2007,  20:03 Найти цитируемый пост)
зачем поинтер и ссылка вместе? разве только передача поинтера не даёт нам тойже, даже большей функциональности как и передача ссылки ?

они тут не вместе, здесь мы имеем ссылку на указатель

Автор: JackYF 25.12.2007, 20:30
Цитата(sgrey @  25.12.2007,  20:03 Найти цитируемый пост)
разве только передача поинтера не даёт нам тойже, даже большей функциональности как и передача ссылки ?

В обоих случаях ты можешь изменить значение по указателю. Передавая же указатель не по ссылке, ты не можешь изменить значение самого указателя. 
Цитата(sgrey @  25.12.2007,  20:03 Найти цитируемый пост)
Для работы с данными класса можно написать внутренний метод - зачем так изголяться? какие преимущества?

Прочитай, к примеру, Design Patterns от Банды 4-х.

Цитата(sgrey @  25.12.2007,  20:03 Найти цитируемый пост)
например - удалить посещаемый элемент....

Паттер "посетитель", емнип, не предполагает деструктивных действий по отношению к посещаемому элементу.

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

Цитата(sgrey @  25.12.2007,  20:03 Найти цитируемый пост)
Зачем поинтер к типу функции?

указатель на функцию. Ему можно присвоить адрес любой функции в райтайме. Примеры и т.д. - в учебниках есть.

Автор: Earnest 25.12.2007, 20:31
1) Это объявление типа "указатель на функцию"; синтаксис такой

2) Судя по всему там у тебя паттер визитер реализуется...
Да, для одного алгоритма проще написать функцию прямо в классе. Т.е. обойти дерево и сделать с каждым узлом нечто.
Но если нужно второй метод обработки, третий... десятый... Что, каждый раз писать обход по новой? Конечно, обход дерева не слишком сложная вещь, но это общий подход.
Паттерн визитер дает гибкость и отделение кода обхода дерева от кода обработки узлов.

3) FunctionType - это просто определение типа. Тебе нужно написать функцию с такой сигнатурой и передать ее в качестве параметра. В функции пиши что хошь, но вот удалять узлы не стоит (по причине сказанного в пункте 2 - может разрушится обход). Впрочем, можно реализовать обход так, чтобы при обработке узлы можно было в том числе и удалять. Только для этого тебе потребуется функция-визитер с параметром (указателем на само дерево) - ибо не имея контейнер, нельзя удалить его элемент. Разве что внутри три-итема есть ссылка на контейнер. 

Автор: sgrey 25.12.2007, 20:32
Цитата(zkv @  25.12.2007,  20:23 Найти цитируемый пост)
не понятен вопрос

имею ввиду что для того чтобы работать с данными класса, можно внутри класса написать функцию, которая также будет показывать treePtr->item, как это делается visit(treePtr->item).
Зачем для этого нужно создавать новый тип функции ?

Цитата(zkv @  25.12.2007,  20:23 Найти цитируемый пост)
FunctionType - это тип а не функция, ты можешь определить свою функцию:

ну да, это и имел ввиду - функцию типа FunctionType )
т.е. я в main потом пишу функцию, которая будет делать нужные мне операции и передаю её в preorder ?
типа preorder(Tree, ViewItem); ?

Добавлено через 5 минут и 35 секунд
Цитата(Earnest @  25.12.2007,  20:31 Найти цитируемый пост)
Судя по всему там у тебя паттер визитер реализуется...

а подробней про него можно?

Цитата(Earnest @  25.12.2007,  20:31 Найти цитируемый пост)
В функции пиши что хошь, но вот удалять узлы не стоит (по причине сказанного в пункте 2 - может разрушится обход). Впрочем, можно реализовать обход так, чтобы при обработке узлы можно было в том числе и удалять. Только для этого тебе потребуется функция-визитер с параметром (указателем на само дерево) - ибо не имея контейнер, нельзя удалить его элемент. Разве что внутри три-итема есть ссылка на контейнер.  

TreeNode - это есть класс, в котором хранится сам item и ссылки на левый и правый элементы.
п.с. ща сообщения до 100 добью и всем плюсики выставлю smile 

Автор: Earnest 25.12.2007, 21:16
Цитата(sgrey @  25.12.2007,  21:32 Найти цитируемый пост)
а подробней про него можно?

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

Цитата(sgrey @  25.12.2007,  21:32 Найти цитируемый пост)
TreeNode - это есть класс, в котором хранится сам item и ссылки на левый и правый элементы.

Значит, имея только итем, можно удалить только его детей. Да и то, если это не разрушит дерево (т.е. это единственное место, где эти ссылки живут, а дерево не содержит общего счетчика или чего-то в этом роде).

Добавлено через 3 минуты и 59 секунд
"паттерны проектирования", конечно

Автор: sgrey 25.12.2007, 21:40
Цитата(Earnest @  25.12.2007,  21:16 Найти цитируемый пост)
Подробнее ищи в сети по ключевым словам "паттерны программирования" "банда четырех". Здесь в форуме тоже были ссылки.
Это из серии "это должен знать каждый" (программист) 

пасиб, поищу smile 

Цитата(Earnest @  25.12.2007,  21:16 Найти цитируемый пост)
Значит, имея только итем, можно удалить только его детей. Да и то, если это не разрушит дерево (т.е. это единственное место, где эти ссылки живут, а дерево не содержит общего счетчика или чего-то в этом роде). 

надо только перестроить структуру дерева от удаляемого элемента вниз после того как удалишь родительский элемент ) функция у меня имеется, могу даже выложить если надо, но вопрос не о том) насколько я понял, то саму функцию типа FunctonType писать надо в main, и добавлять функциональность как тебе захочется ) спасибо за ответы ;)

Автор: bsa 26.12.2007, 11:28
"Функцию типа FunctionType" можно писать где угодно. От обычных функций она ничем не отличается. а FunctionType - это тип "указатель на функцию". И правила для него аналогичны void*. Только есть еще возможность вызывать функцию.

Автор: Earnest 26.12.2007, 18:36
Цитата(sgrey @  25.12.2007,  22:40 Найти цитируемый пост)
надо только перестроить структуру дерева от удаляемого элемента вниз после того как удалишь родительский элемент 

Речь была о том, что для удаления итема, которое требует перестройки дерева, нужен дополнительный параметр - само дерево. Которого нет в сигнатуре FunctionType, поэтому взять его неоткуда. 

Автор: sgrey 26.12.2007, 20:12
Цитата(Earnest @  26.12.2007,  18:36 Найти цитируемый пост)
Речь была о том, что для удаления итема, которое требует перестройки дерева, нужен дополнительный параметр - само дерево. Которого нет в сигнатуре FunctionType, поэтому взять его неоткуда.  

ну всё дерево нам и не нужно, нужно "поднять" всех детей что идут после удалённого элемента
а ссылка на корень дерева имеется в классе )
п.с. предлагаю не спорить, а то масло масленое получается  smile  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)