Ужасно неэффективный путь, который мог бы работать, будет состоять в том, чтобы сохранить копию каждого пересечения в городе в течение каждой минуты дня. Маршрут шины от Elm St. и 2-й к Main St. и 25-й был бы представлен как, скажем,
elm_st_and_2nd[12][30].edges :
elm_st_and_1st[12][35] # 5 minute walk to the next intersection
time = 5 minutes
transport = foot
main_st_and_25th[1][15] # 40 minute bus ride
time = 40 minutes
transport = bus
elm_st_and_1st[12][36] # stay in one place for one minute
time = 1 minute
transport = stand still
Выполнение Ваш любимый новаторский алгоритм на этом графике и молился бы о хорошей реализации виртуальной памяти.
Прочтите этот для получения подробной информации:
// 1 define a function pointer and initialize to NULL
int (TMyClass::*pt2ConstMember)(float, char, char) const = NULL;
// C++
class TMyClass
{
public:
int DoIt(float a, char b, char c){ cout << "TMyClass::DoIt"<< endl; return a+b+c;};
int DoMore(float a, char b, char c) const
{ cout << "TMyClass::DoMore" << endl; return a-b+c; };
/* more of TMyClass */
};
pt2ConstMember = &TMyClass::DoIt; // note: <pt2Member> may also legally point to &DoMore
// Calling Function using Function Pointer
(*this.*pt2ConstMember)(12, 'a', 'b');
Как получить указатель на функцию для функции-члена класса, а затем вызвать этот член функция с конкретным объектом?
Проще всего начать с typedef
. Для функции-члена вы добавляете имя класса в объявление типа:
typedef void(Dog::*BarkFunction)(void);
Затем, чтобы вызвать метод, вы используете оператор -> *
:
(pDog->*pBark)();
Кроме того, если возможно, я хотел бы вызвать конструктор также через указатель. Возможно ли это, и если да, то каков предпочтительный способ сделать это?
Я не верю, что вы можете работать с такими конструкторами - ctors и dtors особенные. Обычный способ добиться такого рода вещей - использовать фабричный метод, который в основном представляет собой статическую функцию, вызывающую за вас конструктор. См. Пример в приведенном ниже коде.
Я изменил ваш код, чтобы в основном делать то, что вы описываете. Ниже приведены некоторые предостережения.
#include <iostream>
class Animal
{
public:
typedef Animal*(*NewAnimalFunction)(void);
virtual void makeNoise()
{
std::cout << "M00f!" << std::endl;
}
};
class Dog : public Animal
{
public:
typedef void(Dog::*BarkFunction)(void);
typedef Dog*(*NewDogFunction)(void);
Dog () {}
static Dog* newDog()
{
return new Dog;
}
virtual void makeNoise ()
{
std::cout << "Woof!" << std::endl;
}
};
int main(int argc, char* argv[])
{
// Call member function via method pointer
Dog* pDog = new Dog ();
Dog::BarkFunction pBark = &Dog::makeNoise;
(pDog->*pBark)();
// Construct instance via factory method
Dog::NewDogFunction pNew = &Dog::newDog;
Animal* pAnimal = (*pNew)();
pAnimal->makeNoise();
return 0;
}
Теперь, хотя вы обычно можете использовать Dog *
вместо Animal *
благодаря магии полиморфизма, тип указателя на функцию делает не следуют правилам поиска иерархии классов. Таким образом, указатель на метод Animal несовместим с указателем на метод Dog, другими словами, вы не можете назначить Dog * (*) ()
переменной типа Animal * (*) ( )
.
Статический метод newDog
представляет собой простой пример фабрики, которая просто создает и возвращает новые экземпляры. Будучи статической функцией, она имеет обычный typedef
(без квалификатора класса).
Ответив на вышеупомянутый вопрос, мне интересно, есть ли ' Не лучший способ достичь того, что вам нужно. Есть несколько конкретных сценариев, в которых вы бы поступили подобным образом, но вы можете обнаружить, что есть другие шаблоны, которые лучше подходят для вашей проблемы. Если вы опишете в более общих выражениях, чего пытаетесь достичь, коллективный разум может оказаться еще более полезным!
В связи с вышесказанным вы, несомненно, найдете библиотеку Boost bind и другие связанные модули очень полезны.
Причина, по которой нельзя использовать указатели функций для вызова функций-членов, заключается в том, что обычные указатели на функции обычно являются просто адресом памяти функции.
Чтобы вызвать функцию-член, вам нужно знать две вещи:
Обычные указатели на функции не могут хранить и то, и другое. Указатели на функции-члены C ++ используются для хранения a), поэтому вам нужно явно указать экземпляр при вызове указателя функции-члена.
Указатель функции на член класса - это проблема, которая действительно подходит для использования boost :: function. Небольшой пример:
#include <boost/function.hpp>
#include <iostream>
class Dog
{
public:
Dog (int i) : tmp(i) {}
void bark ()
{
std::cout << "woof: " << tmp << std::endl;
}
private:
int tmp;
};
int main()
{
Dog* pDog1 = new Dog (1);
Dog* pDog2 = new Dog (2);
//BarkFunction pBark = &Dog::bark;
boost::function<void (Dog*)> f1 = &Dog::bark;
f1(pDog1);
f1(pDog2);
}
Обратите внимание, что, начиная с Java 6, скриптовый API встроен в стандартную библиотеку Java, и вам действительно больше не нужна сторонняя библиотека, такая как Mozilla Rhino. (Фактически, API сценариев в Java 6 является адаптированной версией Mozilla Rhino.)
См. документацию API для пакета javax.script
и см .: Сценарии для платформы Java .
Версия Java по умолчанию в Mac OS X 10.6 (Snow Leopard) - Java 6, поэтому вы должны иметь возможность использовать стандартный API сценариев без установки чего-либо особенного.
Примечание. : Я обнаружил, что jrunscript
установлен на моем Mac, но по какой-то причине его нет в PATH, поэтому он не может найти его, если я наберу jrunscript
в терминале. В моей файловой системе это здесь:
I не думаю, что кто-то объяснил здесь, что одна проблема заключается в том, что вам нужны « указатели на элементы », а не обычные указатели на функции.
Указатели на элементы для функций - это не просто указатели на функции. С точки зрения реализации, компилятор не может использовать простой адрес функции, потому что, как правило, вы не знаете адрес для вызова, пока не узнаете, какой объект разыменовать (подумайте о виртуальных функциях). Вы также должны знать объект, чтобы, конечно, предоставить неявный параметр this
.
Сказав, что они вам нужны, теперь я скажу, что вам действительно нужно их избегать. Серьезно, указатели на члены - это боль. Гораздо разумнее взглянуть на объектно-ориентированные шаблоны проектирования, которые достигают той же цели, или использовать boost :: function
или что-то еще, как упомянуто выше - при условии, что вы можете сделать этот выбор, то есть.
Если вы поставляете этот указатель на функцию в существующий код, поэтому вам действительно нужен простой указатель на функцию, вам следует написать функцию как статический член класса. Статическая функция-член не понимает this
, поэтому вам нужно передать объект в качестве явного параметра. Когда-то в этих строках существовала не такая уж необычная идиома для работы со старым кодом C, которому нужны указатели функций
class myclass
{
public:
virtual void myrealmethod () = 0;
static void myfunction (myclass *p);
}
void myclass::myfunction (myclass *p)
{
p->myrealmethod ();
}
Поскольку myfunction
на самом деле просто обычная функция (не считая проблем с областью видимости), указатель функции может можно найти обычным способом C.
EDIT - этот вид метода называется «методом класса» или «статической функцией-членом». Основное отличие от функции, не являющейся членом, состоит в том, что если вы ссылаетесь на нее извне класса, вы должны указать область с помощью оператора разрешения области ::
. Например, чтобы получить указатель на функцию, используйте & myclass :: myfunction
, а для его вызова используйте myclass :: myfunction (arg);
.
Подобные вещи довольно распространены. при использовании старых API Win32, которые изначально были разработаны для C, а не C ++.
Чтобы создать новый объект, вы можете либо использовать новое размещение, как упомянуто выше, либо реализовать в вашем классе метод clone (), который создает копию объекта. Затем вы можете вызвать этот метод клонирования с помощью указателя на функцию-член, как описано выше, для создания новых экземпляров объекта. Преимущество клонирования состоит в том, что иногда вы можете работать с указателем на базовый класс, когда вы не знаете тип объекта. В этом случае проще использовать метод clone (). Кроме того, clone () позволит вам скопировать состояние объекта, если вы этого хотите.