Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/2: Рейтинг темы: голосов - 2, средняя оценка - 4.50
Segaman
Я в этом не шарю
3 / 3 / 3
Регистрация: 03.09.2014
Сообщений: 175
1

Можно ли объявить два указателя на одну функцию?

21.10.2014, 12:20. Просмотров 493. Ответов 15
Метки нет (Все метки)

есть функция Send(uint type, char*data); но иногда второй аргумент const char*.
можно ли сделать так чтобы на одну функцию Send указывали сразу и Send(uint type, char*data); и Send(uint type, const char*data);
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.10.2014, 12:20
Ответы с готовыми решениями:

в функцию передается два строковых указателя
Добрый день! Функции передается два указателя на массив строк. Пользователь вводит строки,...

Можно ли объявить дружественную функцию как шаблон?
Так всё работает: template<class T> class random { /*всячина*/ public: friend void...

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

Можно ли в цикле for объявить более чем одну переменную?
Господа, подскажите пожалуйста совершенно нелепый вопрос. Можно ли в цикле for объявить более чем...

Можно ли на одну ссылку прикрепить два перехода?
Чтобы, например, при нажатии на слово "Ссылка" активировались две ссылки, т.е. в одной ссылке две...

15
angryjack93
7 / 3 / 2
Регистрация: 04.11.2012
Сообщений: 218
21.10.2014, 12:33 2
через шаблоны можно сделать. Это например так.

C++
1
template <class A> void Send(uint type, A data);
Вообще в любой книжке по C++ можно про обобщенные (шаблонные) функции почитать.
0
ForEveR
В астрале
Эксперт С++
8009 / 4766 / 654
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
21.10.2014, 12:53 3
Segaman, Если функция работает одинаково при обоих аргументах и не изменяет data, можно просто оставить одну функцию
C++
1
Send(uint, const char*);
1
Evg
Эксперт CАвтор FAQ
20448 / 7968 / 616
Регистрация: 30.03.2009
Сообщений: 22,171
Записей в блоге: 30
21.10.2014, 14:19 4
Цитата Сообщение от Segaman Посмотреть сообщение
есть функция Send(uint type, char*data); но иногда второй аргумент const char*
Такая ситуация сама по себе некорректна. Если второй параметр функции Send имеет тип "char*", значит подразумевается, что по указателю можно записывать. Следовательно, подавать туда const char* нельзя. Если же внутри функции Send по указателю не делается никаких записей, то параметр следует обозвать как "const char *data". В этом случае уже вполне корректно будет построить преобразование типов

C++
void Send(unsigned type, const char *data);
void (*fptr1)(unsigned, char*) = (void (*)(unsigned, char*)) Send;
void (*fptr2)(unsigned, const char*) = Send;
0
21.10.2014, 14:19
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
5520 / 2696 / 740
Регистрация: 18.10.2014
Сообщений: 4,785
21.10.2014, 21:10 5
Цитата Сообщение от Evg Посмотреть сообщение
Такая ситуация сама по себе некорректна. Если второй параметр функции Send имеет тип "char*", значит подразумевается, что по указателю можно записывать.
Ну, это так, но не совсем так. А именно: если в функцию передается неконстантный указатель (под этим я буду подразумевать "указатель не на константный тип") это совсем не означает, что функция собирается модифицировать указуемые данные.

Элементарный пример. Захотели мы написать функцию, которая ищет конкретный символ в строке и возвращает указатель на него. И написали мы ее вот так

C++
1
2
3
4
char *find_character(char *str, char c) {
   for (char *pc = str; *pc != '\0' && *pc != c; ++pc);
   return pc;
}
Заметьте, функция сама не меняет никаких данных, но все равно мы должны передавать туда 'char *' (a не 'const char *') потому, что хотим обратно из функции получать именно 'char *'. А хотим мы получать именно 'char *' потому, что использовать эту фукцию мы будем в том числе вот как-то так

C++
1
2
3
4
char str[] = "Stupid Trick";
char *p = find_character(str, 'T');
assert(*p != '\0');
*p = 'P';
Но в один прекрасный день мы попали в ситуацию, когда нам надо было сделать так

C++
1
2
3
4
const char *str = "9876543210";
const char *p = find_character(str, '5');
assert(*p != '\0');
unsigned index = p - str;
и, по понятным причинам, у нас ничего не получилось. Вроде запрос вполне естественный, но код не компилируется. Что делать?

В языке С++ в такой ситуации традиционно принято яростно придерживаться правил константной корректности и предоставлять вторую версию функции через механизм перегрузки функции

C++
1
2
3
4
const char *find_character(const char *str, char c) {
   for (const char *pc = str; *pc != '\0' && *pc != c; ++pc);
   return pc;
}
А чтобы избежать тупого повторения одной и то же реализации функции, реализуют традиционно именно константную версию, а вот неконстантную перенаправляют в константную вот так

C++
1
2
3
inline char *find_character(char *str, char c) {
   return const_cast<char *>(find_character(const_cast<const char *>(str), c));
}
Вот и все.

Но это в С++. А что делать в С, где механизма перегрузки функций нет?

Особые педанты и поборники константной корректности в С стараются эмулировать С++, заводя две функции с разными именами

C
1
2
3
4
5
6
7
8
const char *find_character_с(const char *str, char c) {
   for (const char *pc = str; *pc != '\0' && *pc != c; ++pc);
   return pc;
}
 
inline char *find_character(char *str, char c) {
   return (char *) find_character_с(str, c);
}
и потом просто вызывают подходящую функцию вручную.

Но в языке С с незапамятных времен существовала и другая популярная идиома. Просто-напросто пишем одну-единственную функцию-гибрид

C
1
2
3
4
char *find_character_с(const char *str, char c) {
   for (const char *pc = str; *pc != '\0' && *pc != c; ++pc);
   return (char *) pc;
}
и используем ее на все случаи жизни. Обратите внимание, что функция написана "опасно": она использует явный каст и возвращает неконстантный указатель на потенциально константные данные. Но сама по себе функция ничего нелегального не делает - она не пытается ничего нигде модифицировать. Поэтому в данном случае ответственность на правильное использование указателей просто ложится на вызывающий код: если вы передавали в функцию константный указатель, то и результат извольте по-джентельменски принимать в константный указатель. И все будет хорошо.

Эта идиома широко используется в стандартной библиотеке языка С: посмотрите на функции 'strstr', 'strchar', 'strrchr' - именно так они реализованы.

А уж как вы хотите поступать - решать вам. А С++ коде предпочтительнее, наверное, избегать этой С-шной идиомы. В С же коде ничего зазорного в ней нет.
0
Evg
Эксперт CАвтор FAQ
20448 / 7968 / 616
Регистрация: 30.03.2009
Сообщений: 22,171
Записей в блоге: 30
21.10.2014, 21:17 6
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
если в функцию передается неконстантный указатель (под этим я буду подразумевать "указатель не на константный тип") это совсем не означает, что функция собирается модифицировать указуемые данные
А я где-то утверждал, что функция собирается модифицировать по указателю?
0
Kuzia domovenok
2832 / 2419 / 619
Регистрация: 25.03.2012
Сообщений: 8,621
Записей в блоге: 1
Завершенные тесты: 1
21.10.2014, 21:23 7
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Ну, это так, но не совсем так. А именно: если в функцию передается неконстантный указатель (под этим я буду подразумевать "указатель не на константный тип") это совсем не означает, что функция собирается модифицировать указуемые данные.
много слов, а по сути ерунда.
Если твоя функция не изменяет данные, объявляй её аргумент const char*. Всё. Вопрос закрыт.
В такую функцию можно передаваить и константы и неконстанты тоже! ты это понять вообще можешь?
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
5520 / 2696 / 740
Регистрация: 18.10.2014
Сообщений: 4,785
21.10.2014, 21:44 8
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
много слов, а по сути ерунда.
Не "ерунда", а основы константой корректности языков С и С++. Читай сначала, много раз, до просветления.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Если твоя функция не изменяет данные, объявляй её аргумент const char*. Всё. Вопрос закрыт. В такую функцию можно передаваить и константы и неконстанты тоже! ты это понять вообще можешь?
Ну так расскажи-ка нам, знающий ты наш, каким образом ты предлагаешь получать из функции некостантный указатель, если туда передавал константный. Элементарные примеры приведены в моем посте: давайте-ка взглянем на твою версию функции, в которую "можно передаваить и константы и неконстанты тоже". Тебя ведь не затруднит всего две строчки написать? Я весь внимание

P.S. "Как все запущено..." (с)

Добавлено через 4 минуты
Цитата Сообщение от Evg Посмотреть сообщение
А я где-то утверждал, что функция собирается модифицировать по указателю?
Да, разумеется. Тот ваш пост, на который я отвечал, прямо говорит, что константность параметра связана с тем, собирается ли функция модифицировать данные.
0
Evg
Эксперт CАвтор FAQ
20448 / 7968 / 616
Регистрация: 30.03.2009
Сообщений: 22,171
Записей в блоге: 30
21.10.2014, 21:45 9
"подразумевается, что по указателю можно записывать" и "прямо говорит, что константность параметра связана с тем, собирается ли функция модифицировать данные" по твоему это одно и то же? Ну-ну
0
Kastaneda
21.10.2014, 22:02
  #10

Не по теме:

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
много слов, а по сути ерунда.
TheCalligrapher, все правильно расписал, зря прицепились.

0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
5520 / 2696 / 740
Регистрация: 18.10.2014
Сообщений: 4,785
21.10.2014, 22:24 11
Цитата Сообщение от Evg Посмотреть сообщение
"подразумевается, что по указателю можно записывать" и "прямо говорит, что константность параметра связана с тем, собирается ли функция модифицировать данные" по твоему это одно и то же? Ну-ну
Ну зачем же так вертеться? "Прямо говорят" такие твои слова, как, например, (цитирую) "Если же внутри функции Send по указателю не делается никаких записей, то параметр следует обозвать как "const char *data".
0
Evg
21.10.2014, 22:28
  #12

Не по теме:

После всего этого меня уже вовсе не удивляют ассоциации с зелёным кругом

0
Kuzia domovenok
2832 / 2419 / 619
Регистрация: 25.03.2012
Сообщений: 8,621
Записей в блоге: 1
Завершенные тесты: 1
22.10.2014, 16:15 13
Цитата Сообщение от Kastaneda Посмотреть сообщение
TheCalligrapher, все правильно расписал, зря прицепились.
а что он по теме-то написал?
Я не цепляюсь, но по-моему, он очень длинно и нудно расписал набор банальностей "в функцию foo(char*) можно передавать и константные строки и нет, а в foo(const char*) только константные"...
Ну и что? Капитан очевидность, как это к теме-то относится?

Добавлено через 10 минут
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
"в функцию foo(char*) можно передавать и константные строки и нет, а в foo(const char*) только константные"...
тьфу ты! наоборот!
0
TheCalligrapher
С чаем беда...
Эксперт CЭксперт С++
5520 / 2696 / 740
Регистрация: 18.10.2014
Сообщений: 4,785
22.10.2014, 17:25 14
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
а что он по теме-то написал?
Я не цепляюсь, но по-моему, он очень длинно и нудно расписал набор банальностей "в функцию foo(char*) можно передавать и константные строки и нет, а в foo(const char*) только константные"...
Зрителям: Прикольно, кстати, читать вот таких деятелей, как вышепроцитированный индивидуум

В первом ответ на тот мой пост он написал (цитирую): "В такую функцию можно передаваить и константы и неконстанты тоже! ты это понять вообще можешь?". Теперь же он вдруг пишет (цитирую): "он очень длинно и нудно расписал набор банальностей "в функцию foo(char*) можно передавать и константные строки и нет, а в foo(const char*) только константные".

Немая сцена. Вот такой вот у нас набор контрастов Вчера одно, сегодня - совсем другое

И это при том, что, разумеется, содержание того моего сообщения никакого отношения к вышепроцитированным домовическим "банальностям" не имело. Понимания этого, я вижу, у данного индивидуума пока не возникло. Ответа на вопрос о том, как же "правильно" написать рассматриваемую функцию в соответствии с озвученным ранее залихватским Гениальным Принципом "Функция данных не меняет - значит смело пиши const !!!!111", я так понимаю, мы тоже не дождемся...
0
MrGluck
22.10.2014, 18:03
  #15

Не по теме:

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
много слов, а по сути ерунда.
кому как. ИМХО, всё по делу

0
taras atavin
4200 / 1777 / 211
Регистрация: 24.11.2009
Сообщений: 27,563
22.10.2014, 18:05 16
Цитата Сообщение от Segaman Посмотреть сообщение
есть функция Send(uint type, char*data); но иногда второй аргумент const char*.
можно ли сделать так чтобы на одну функцию Send указывали сразу и Send(uint type, char*data); и Send(uint type, const char*data);
Это вообще то две разные функции, а не указателя.
0
22.10.2014, 18:05
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.10.2014, 18:05

Можно ли в одну ячейку вставить два числа?
Добрый день! Я учитель, делаю в Excel (а точнее, в таблицах гугл) для себя журнал с отметками....

Как сделать функцию от указателя на класс и указателя на метод?
Не получается сделать функцию, параметрами которой являются указатель на класс и на метод....

Есть хоть один язык программирования, в котором переменную или функцию можно объявить после её использования?
Хочу в своём такое реализовать, но так значительно увеличится скорость компиляции. Не знаю, стоит...


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

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

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