Существует несколько способов заняться им.
интуитивный подход, который является тем, о чем думает большинство программистов C/C++, состоит в том, что указатели являются адресами памяти. пример litb проявляет этот подход. Если у Вас есть нулевой указатель (который на большинстве машин соответствует адресу 0), и Вы добавляете размер интервала, Вы получаете адрес 4. Это подразумевает, что указатели являются в основном просто необычными целыми числами.
, К сожалению, существует несколько проблем с этим. Для начала это не может работать. Нулевой указатель, как гарантируют, на самом деле не будет использовать адрес 0. (Хотя присвоение постоянного 0 к указателю приводит к нулевому указателю).
Далее, Нельзя увеличить нулевого указателя, или в более общем плане, указатель должен всегда указывать на выделенную память (или один элемент мимо), или специальный нулевой указатель постоянный 0.
, Таким образом, более корректный образ мыслей его - то, что указатели являются просто итераторами, разрешающими Вам выполнить итерации по выделенной памяти. Это - действительно одна из ключевых идей позади итераторов STL. Они смоделированы, чтобы вести себя очень как указатели и обеспечить специализации, которые исправляют необработанные указатели для работы надлежащими итераторами.
А более тщательно продуманное объяснение этого дано здесь , например.
, Но это последнее представление означает, что необходимо действительно объяснить итераторы STL, и затем просто сказать, что указатели являются особым случаем их. Можно увеличить указатель для указания на следующий элемент в буфере, точно так же, как Вы можете std::vector
. Это может указать на один элемент мимо конца массива, точно так же, как конечный итератор в любом другом контейнере. Можно вычесть два указателя , что точка в тот же буфер для получения числа элементов между ними, точно так же, как Вы можете с итераторами, и точно так же, как с итераторами, если указатели указывают в отдельные буферы, Вы можете не , обоснованно сравнивают их. (Для практического примера почему не, рассмотрите то, что происходит в сегментированном пространстве памяти. Каково расстояние между двумя указателями, указывающими для разделения сегментов?)
, Конечно, на практике, существует очень близкая корреляция между адресами ЦП и указателями C/C++. Но они не точно то же самое. Указатели имеют несколько ограничений, которые не могут быть строго необходимыми на Вашем ЦП.
, Конечно, большинство программистов на C++ запутывает на первом понимании, даже при том, что это технически неправильно. Это достаточно обычно близко к тому, как Ваш код заканчивает тем, что вел себя, что люди думают, что получают его и идут дальше.
, Но для кого-то происходящего из Java, и просто узнающий об указателях с нуля, последнее объяснение может быть столь же понятным, и это собирается преподнести меньше сюрпризов на них позже.
Python предполагает, что любые функции, связанные в рамках класса, являются методами. Если вы хотите рассматривать их как функции, вы должны покопаться в их атрибутах, чтобы получить исходный объект функции:
def __init__(self, *args, **kwargs):
super(Fruit, self).__init__(*args, **kwargs)
# The attribute name was changed in Python 3; pick whichever line matches
# your Python version.
callback = self.print_callback.im_func # Python 2
callback = self.print_callback.__func__ # Python 3
callback("Message from Fruit: ")
There's also a bit dirtyer solution with metaclasses:
def apple_print(f):
print "Apple " + f
class FruitMeta(type):
def __new__(cls, name, bases, dct):
func = dct["print_callback"]
dct["print_callback"]=lambda x,f,func=func: func(f)
return type.__new__(cls,name,bases,dct)
class Fruit(object):
__metaclass__ = FruitMeta
print_callback = None
def __init__(self):
super(Fruit,self).__init__()
self.print_callback("Msg ")
class Apple(Fruit):
print_callback = apple_print
mac = Apple()here
It manipulates the class before its creation!
Вы можете использовать напрямую:
class Apple(Fruit):
print_callback = staticmethod(apple_print)
или:
class Apple(Fruit):
print_callback = classmethod(apple_print)
В первом случае вы получите только один параметр (оригинал). Во втором вы получите два параметра, где первый будет классом, для которого он был вызван.
Надеюсь, это поможет, и он будет короче и менее сложным.
Обновлено : добавлено предложение abourget об использовании статического метода
:
Попробуйте следующее:
def __init__(self, *args, **kwargs):
super(Fruit, self).__init__(*args, **kwargs)
# Wrap function back into a proper static method
self.print_callback = staticmethod(self.print_callback)
# And now you can do:
self.print_callback("Message from Fruit: ")