C++. Сборник рецептов - [202]
>vector
Или их массив?
>bool (*af[10])(int);
Форма представления указателей на функции отличается от обычных переменных С++, которые обычно задаются в виде (квалифицированного) имени типа, за которым идет имя переменной. Поэтому они вносят путаницу при чтении программного кода.
Итак, в примере 15.1 я использовал следующий >typedef
.
>typedef bool (*FuncPtrBoolInt)(int);
Сделав это, я могу свободно объявлять указатели функций с сигнатурой, возвращающей значение >bool
и принимающей единственный аргумент, как это я бы делал для параметра любого другого типа, например.
>void longOperation(FuncPtrBoolInt f) { // ...
Теперь все, что надо сделать в >longOperation
, — это вызвать >f
, как если бы это была любая обычная функция.
>f(l/1000000);
Таким образам, здесь >f
может быть любой функцией, которая принимает аргумент целого типа и возвращает >bool
. Предположим, что в вызывающей функции >longOperation
не требуется обеспечивать продвижение индикатора состояния процесса. Тогда ей можно передать указатель на функцию без операций.
>bool whoCares(int i) {return(true);}
>//...
>longOperation(whoCares);
Более важно то, что выбор функции, передаваемой >longOperation
, может осуществляться динамически на этапе выполнения.
15.2. Применение указателей для членов класса
Требуется обеспечить адресную ссылку на данное-член или на функцию-член.
Используйте имя класса и оператор области видимости (>::
) со звездочкой для правильного квалифицирования имени. Пример 15.2 показывает, как это можно сделать.
Пример 15.2. Получение указателя на член класса
>#include
>#include
>class MyClass {
>public:
> MyClass() : ival_(0), sval_("foo") {}
> ~MyClass() {}
> void incr() {++ival_;}
> void decr() {ival_--;}
>private:
> std::string sval_;
> int ival_;
>};
>int main() {
> MyClass obj;
> int MyClass::* mpi = &MyClass::ival_; // Указатели на
> std::string MyClass::* mps = &MyClass::sval_; // данные-члены
> void (MyClass::*mpf)(); // Указатель на функцию-член, у которой
> // нет параметров и которая возвращает void
> void (*pf)(); // Обычный указатель на функцию
> int* pi = &obj.ival_; // int-указатель, ссылающийся на переменную-член
> // типа int, - все нормально.
> mpf = &MyClass::incr; // Указатель на функцию-член. Вы не можете
> // записать это значение в поток. Посмотрите в
> // отладчике, как это значение выглядит.
> pf = &MyClass::incr; // Ошибка: &MyClass::inc не является экземпляром
> // функции
> std::cout << "mpi = " << mpi << '\n';
> std::cout << "mps = " << mps << '\n';
> std::cout << "pi = " << pi << '\n';
> std::cout << "*pi = " << *pi << '\n';
> obj.*mpi = 5;
> obj.*mps = "bar";
> (obj.*mpf)(); // теперь obj.ival_ равно 6
> std::cout << "obj.ival_ = " << obj.ival_ << '\n';
> std::cout << "obj.sval_ = " << obj.sval_ << '\n';
>}
Указатели на члены класса выглядят и работают иначе, чем обычные указатели. Прежде всего, они имеют «смешной» синтаксис (не вызывающий смех, но странный). Рассмотрим следующую строку из примера 15.2.
>int MyClass::* mpi = &MyClass::ival_;
Здесь объявляется указатель и ему присваивается значение целого типа, которым оказывается член класса >MyClass
. Две вещи отнимают это объявление от обычного >int*
. Во-первых, вам приходится вставлять имя класса и оператор области видимости между типом данного и звездочкой. Во-вторых, при выполнении операции присваивания этому указателю на самом деле не назначается какой то определенный адрес памяти. Значение >&MyClass::ival_
не является каким-то конкретным значением, содержащимся в памяти; оно ссылается на имя класса, а не на имя объекта, но тогда что же это такое на самом деле? Можно представить это значение как смешение данного-члена относительно начального адреса объекта.
Переменная >mpi
должна использоваться совместно с экземпляром класса, к которому она применяется. Немного ниже в примере 15.2 располагается следующая строка, которая использует >mpi
для присваивания целого числа значению, на которое ссылается указатель >mpi
.
>obj.*mpi = 5;
>obj
является экземпляром класса >MyClass
. Ссылка на член с использованием точки (или >->
, если у вас имеется указатель на >obj
) и разыменование >mpi
позволяют вам получить ссылку на >obj.ival_
.
Указатели на функции-члены действуют фактически так же. В примере 15.2 объявляется указатель на функцию-член >MyClass
, которая возвращает >void
и не имеет аргументов.
>void (MyClass::*mpf)();
Ему можно присвоить значение с помощью оператора адресации.
>mpf = &MyClass::incr;
Для вызова функции заключите основное выражение в скобки, чтобы компилятор понял ваши намерения, например:
>(obj.*mpf)();
Однако имеется одно отличие в применении указателей на данные-члены и указателей на функции члены. Если необходимо использовать обычный указатель (не на член класса) на данное-член, просто действуйте обычным образом.
>int* pi = &obj.ival_;
Конечно, вы используете имя объекта, а не имя класса, потому что получаете адрес конкретного данного-члена конкретного объекта, расположенного где-то в памяти. (Однако обычно стараются адреса данных-членов класса не выдавать за его пределы, чтобы нельзя было их изменить из-за опрометчивых действий в клиентском программном коде.)
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.