2010-11-09 4 views
0

Я видел следующий код:
http://sourcemaking.com/design_patterns/singleton/cpp/1Может ли статическая переменная-член вызывать нестатические функции-члены?

class GlobalClass 
{ 
private: 
    int m_value; 
    static GlobalClass *s_instance; 
    GlobalClass(int v = 0) 
    { 
     m_value = v; 
    } 
public: 
    int get_value() 
    { 
     return m_value; 
    } 
    void set_value(int v) 
    { 
     m_value = v; 
    } 
    static GlobalClass *instance() 
    { 
     if (!s_instance) 
      s_instance = new GlobalClass; 
     return s_instance; 
    } 
}; 

GlobalClass *GlobalClass::s_instance = 0; 

void foo(void) 
{ 
    GlobalClass::instance()->set_value(1); // static variable calls non-static functions 
    cout << "foo: global_ptr is " << GlobalClass::instance()->get_value() << '\n'; 
} 

Насколько я знаю (поправьте меня, если я ошибаюсь, здесь),

  1. Статические функции могут только доступ (запись/чтение) статические переменные-члены

  2. Функции, не являющиеся статическими, могут иметь доступ к переменным статическим членам (запись/чтение)

На основании вышеприведенного образца кажется, что статическая переменная может обращаться к нестационарным функциям.
Это правильно?

ответ

5

Переменные не называть что-либо

(Это на самом деле не обратиться образец кода, но он исправляет неправильное представление в двух «правил», перечисленных под кодом)

Статический член функция является членом и может обращаться ко всем открытым, защищенным и закрытым членам своего класса, как статическим, так и экземплярам.

Однако статические функции-члены не имеют указателя this, поэтому для доступа к члену экземпляра экземпляр необходимо указать.

+2

Статическая функция-член не может получить доступ к нестатической переменной-члену. – q0987

+5

@ q0987: Да, может. Я могу привести вам пример, но я бы предпочел, чтобы вы сначала остановились и подумали о моем ответе. Научиться думать о программном обеспечении - очень важная часть обучения программированию. –

+3

Вот ваш пример: http://ideone.com/gX5wF –

3

instance, как следует из его названия, возвращает указатель на экземпляр. Он также использует статическое поле указателя экземпляра, s_instance. Тот факт, что это статичный, означает, что в классе есть только одно поле s_instance. Как только вы получите указатель этого экземпляра (от instance), вы можете использовать его, как и любой другой указатель экземпляра. Факты, которые вы получили с помощью статического метода и что метод использует статическое поле, не имеют значения.

Сам статический метод действителен; он не использует явно или явно не this.

+0

Более краткий, чем я мог бы управлять. Я думаю, он также смущен тем, что 's_instance' сам статичен, а не только метод, по которому он получает указатель. – Phil

+0

@Phil, хороший момент. Я добавил некоторое обсуждение этой области. –

4

Кажется, что статическая переменная может обращаться к нестационарным функциям.

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

Чтобы понять, что он делает, давайте немного подберемся и поговорим о том, что действительно означает class. классы определяют новые типы. другой тип: int. экземпляр int может быть расположен в функциях локальных переменных или параметров, он может быть сохранен в куче, вызывая new int, он может быть глобальным, объявив одно в области файла. ни один из них не знает или не заботится о том, где они хранятся, но все они являются экземплярами типа int.

Когда вы делаете экземпляр class, вы создаете пространство и поведение в экземпляре этого класса, и эти поведения применяются ко всем экземплярам одинаково.

классы также могут делать что-то, что не является частью определения данных и поведения его экземпляров, и это статические члены класса.

Поскольку эти концепции принципиально раздельны, они на самом деле не мешают друг другу. на самом деле, вы могли бы иметь один из статических членов класса, относящихся к экземпляру класса, и это именно то, что делает этот пример шаблона singleton.

Так что происходит на самом деле, с самого начала вы создаете экземпляр класса, используя new GlobalClass, а затем сохраняя указатель где-то. Бывает, что указатель сохраняется как статический член того же класса, который определяет тип созданного экземпляра.

затем GlobalClass предоставляет механизм для использования этого экземпляра. когда вы вызываете GlobalClass::instance(), он читает статическую переменную класса, которая разрешена. переменная содержит указатель, который при разыменовании (через ->) приводит к созданию одного объекта, который мы создали ранее, и этот объект, поскольку он является экземпляром GlobalClass, теперь имеет доступ к переменной экземпляра.

+0

Hello TokenMacGuy, GlobalClass :: instance() возвращает s_instance, который является статической переменной-членом. Поэтому я предполагаю, что эта функция возвращает статическую переменную-член. Я прав? - спасибо – q0987

+0

@ q0987 - да, это правильно. Статические методы не могут получить доступ к нестационарным методам, но экземпляр - статический или другой - может получить доступ к обоим. – Phil

+0

@Phil, это то, что я чувствую смущение. Поскольку возвращаемый экземпляр является статической переменной. Как эта статическая переменная вызывает нестационарную функцию-член set_value и изменяет нестационарную переменную-член m_value? Другими словами, как статическая переменная определяет, какое «это» использовать? - спасибо – q0987

1

Технические вопросы уже опубликованы в других ответах. Я просто добавлю пример, пытаясь помочь с путаницей. Представьте, что вы создаете класс Human для представления человека, он может иметь свойства, такие как цвет глаз, имя и т. Д. ... и методы, которые определяют действия, такие как прогулка, прыжок ... эти свойства и методы являются конкретными для каждого пример человека: у конкретного человека могут быть голубые глаза, и вы можете попросить ее поговорить.

На другом уровне могут существовать свойства или действия, которые не относятся к экземпляру , а относятся ко всему классу людей, например, кто является самым высоким или старшим человеком. Они объявлены статическими как принадлежащие всему набору людей, а не каждому человеку.

Теперь, как только вы получаете человека из класса, скажем, самого высокого, это лицо является Человеком, и поэтому вы можете запросить любое свойство, которое вы хотите, или можете запросить любые необходимые действия: Human::get_tallest().get_something_from_cupboard() запросит самую высокую (get_tallest()) Человек в наборе (действие класса), а затем попросите конкретного человека выполнить действие для вас (get_something_from_cupboard()), которое является действием, выполняемым конкретным экземпляром .

Смежные вопросы