2014-09-24 4 views
3

Я пытаюсь понять статические элементы немного больше, и я экспериментировал с фрагментами кода, чтобы увидеть, что работает/является законным, а что нет.Доступ к частному статическому члену через экземпляр объекта

Я понимаю, что статическая переменная не находится внутри класса/структуры, но является отдельной. Другими словами, переменную y в коде ниже следует получить по адресу A::y, а не this->y, поэтому мое предположение заключалось в том, что код ниже не будет компилироваться. Я был удивлен, что это произошло (MingGW).

Может кто-нибудь объяснить, как этот механизм доступа работает и реализуется.

// ClassA.h 
class A{ 
    private: 
    int x; 
    static int y; 
    public: 
    void setX(int x){this->x = x;} 
    void setY(int y){this->y = y;} 
} 

// main.cpp 
#include "ClassA.h" 

int main (int argc,char* argv[]){ 
    A my_A; 
    my_A.setX(5); 
    my_A.setY(10); 
    return 0; 
} 
+0

Статические переменные находятся в классе (они принадлежат самому классу). И по-прежнему можно получить доступ к статическому члену через оператор доступа к члену класса. – 0x499602D2

+0

Почему я получаю сообщение об ошибке при компиляции кода? г ++ -o тест main.cpp '/tmp/cciEVrgm.o: В функции 'A :: SetY (INT)':. main.cpp :(text._ZN1A4setYEi [_ZN1A4setYEi] + 0x10): неопределенная ссылка to 'A :: y' collect2: error: ld received 1 exit status' –

+0

Я не добавлял определение статического члена 'y' для простоты. Извини за это. –

ответ

7

Это работает, потому что язык позволяет это. Указатель this используется только в этом контексте; когда элемент обнаружен как статический, указатель не будет использоваться. То есть, скомпилированный код вообще не будет использовать указатель.

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

Дополнительная литература: Accessing static members via an instance (содержит несколько примеров, когда этот метод может быть полезен)


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

#include <iostream> 

class Foo { 
public: 
    static int x; 
}; 

int Foo::x = 0; 

Foo aFoo; 

Foo & test() { 
    std::cout << "test()" << std::endl; 
    return aFoo; 
} 

int main(void) { 
    test().x = 1; 

    return 0; 
} 

компилятор знает, что во время компиляции, где test().x есть, потому что он знает, что test() возвращает ссылку на Foo и Foo::x статична - но даже если компилятор знает, где чтобы найти test().x без фактического испускающего кода, который оценивает test(), он все еще испускает вызов функции и просто игнорирует результат, потому что альтернатива (вообще не вызов) может быть еще более запутанной.

В этом примере test().x = 1; эквивалентен (test(), Foo::x = 1);.

0

Can someone please explain how this access mechanism works

Все потребности компилятора - это тип указателя, который он знает. Его фактическое значение игнорируется, даже если оно равно нулю.

and is implemented

Оба ваших примера скомпилированы по одному и тому же коду.

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