класс статическая функция-член, выбранная над глобальной функцией с тем же именем? - PullRequest
10 голосов
/ 29 апреля 2011

Отсюда возникло сомнение


int g() {
   cout << "In function g()" << endl;
   return 0;
}

class X {
public:
  static int g() {
     cout << "In static member function X::g()" << endl;
     return 1;
  }
};

class Y: public X {
   public:
  static int i;
};

int Y::i = g();   

Первоначально я полагал, что, поскольку разрешение символов происходит от самой внутренней области видимости до самой внешней,почему вызывается x :: g ().
, но потом я внимательно заметил код

int Y::i = g();

как мы можем получить доступ к X :: g () без именной области?
И область, в которой лежит это утверждение, должна быть глобальной, а не Y :: или X ::, поэтому разрешение символов должно давать глобальную версию функции g ()?

Ответы [ 2 ]

11 голосов
/ 29 апреля 2011

Примечание: я думаю, что мой предыдущий ответ был неправильным.Это не Поиск Кенига , т.е. поиск имени в зависимости от аргумента (ADL).Поэтому я удалил свой (более ранний) ответ, поскольку нашел соответствующий раздел в Стандарте, который отвечает на ваш вопрос.

Ваш код прямо из раздела §9.4 / 2 Стандарта C ++ 03.

На статический член можно ссылаться непосредственно в области его класса или в области класса, полученного (пункт 10) из его класса;в этом случае статический член упоминается так, как если бы использовалось выражение квалифицированного идентификатора, а спецификатор вложенного имени квалифицированного идентификатора именовал область класса, из которой ссылается статический член.

Затем приводится этот пример (который вы задали в вопросе)

[Example:

    int g();
    struct X {
        static int g();
    };
    struct Y : X {
        static int i;
    };
    int Y::i = g(); // equivalent to Y::g();

—end example]

Затем говорится, что в §9.4 / 3

Еслиunqualified-id (5.1) используется в определении статического члена после идентификатора объявления члена, а name lookup (3.4.1) обнаруживает, что unqualified-id ссылается на статический член enumerator,или вложенный тип класса члена (или базового класса класса члена), неквалифицированный идентификатор преобразуется в выражение квалифицированного идентификатора, в котором спецификатор вложенного имени называет область действия класса, на которую ссылается член .

Поскольку это происходит только в определении статического члена, это означает, что Y::g() вызывается ТОЛЬКО при инициализации , нв назначение :

//definition-cum-initialization
int Y::i = g(); // equivalent to Y::g();
int main()
{
   //assignment 
   Y::i = g(); // does not equivalent to Y::g(); it calls global g()
}

См. вывод здесь: http://www.ideone.com/6KDMI

Давайте рассмотрим другой пример:

struct B{};

B f();

namespace NS 
{
   struct A { static B b;};
   B f();
}

//Definition cum Initialization
B NS::A::b = f();  //calls NS::f()
B b = f();         //calls global f()

int main() 
{
   //Assignment
   NS::A::b = f(); //calls global f()
   b = f();        //calls global f()
}

См. полныйдемо здесь: http://www.ideone.com/53hoW

9 голосов
/ 29 апреля 2011

Это потому, что вы используете int Y::i =..., обратите внимание на Y::. Вот почему он на самом деле ищет g() внутри Y, то есть X::g(), потому что Y выводит X.


Дополнение: например, если вы поставите int i = g(); после int Y::i = g();, результат будет:

In static member function X::g()
In function g()

РЕДАКТИРОВАТЬ : точно - поиск имени в зависимости от аргумента. Я не мог вспомнить, как это называется в начале. Спасибо Навазу ответ (:

РЕДАКТИРОВАТЬ2 : ОК, Наваз нашел правильное объяснение, оно в стандарте и, похоже, не «поиск имени в зависимости от аргумента». Но логика все еще абсолютно та же самая.

...