Определение члена пространства имен против свободных функций без квалификации - PullRequest
0 голосов
/ 24 августа 2011

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

Добавление «использования пространства имен» (или, для более точного нацеливания, «использования :: SomeClass») до того, как я определю функции-члены, похоже, избавляет от необходимости уточнять каждое определение, но я не могу найти нигде в спецификации, что гарантирует это, и я беспокоюсь, что это может быть поведение, которое работает только с GCC. Я отмечаю, что, похоже, не существует аналогичного механизма для пропуска необходимости добавлять квалификаторы при определении свободных функций (?).

В качестве примера того, что я имею в виду:

Заголовок:

// example.h
namespace SomeNamespace
{
    class SomeClass
    {
    public:
        void someMemberFunction();
    };

    void someFreeFunction();
};

Реализация:

// example.cpp
#include "example.h"

using namespace SomeNamespace;

void SomeClass::someMemberFunction()
{
    // OK: seems to define SomeNamespace::SomeClass::someMemberFunction(),
    // even though we didn't qualify it with SomeNamespace::
}

void someFreeFunction()
{
    // Not what we wanted; declares and defines ::someFreeFunction(), not
    // SomeNamespace::someFreeFunction() (quite understandably)
}

int main()
{
    SomeClass a;
    a.someMemberFunction(); // Ok; it is defined above.
    SomeNamespace::someFreeFunction(); // Undefined!
    return 0;
}

Итак, мой вопрос: является ли приведенный выше способ определения SomeClass :: someMemberFunction () допустимым, и где в спецификации это упоминается? Если это законно, целесообразно ли это? Это, конечно, сокращает беспорядок! :)

Большое спасибо:)

Ответы [ 2 ]

2 голосов
/ 24 августа 2011

Возможно, я ошибаюсь, но если у вас есть:

// example.h
namespace SomeNamespace
{
    class SomeClass
    {
    public:
        void someMemberFunction();
    };

    void someFreeFunction();
};

Вы также можете просто написать:

#include "example.h"

// example.cpp
namespace SomeNamespace
{
    void SomeClass::someMemberFunction()
    {
    }

    void someFreeFunction()
    {
    }
}
0 голосов
/ 24 августа 2011

Когда вы определяете функцию-член, компилятор понимает, что это функция-член, которая должна принадлежать ранее объявленному классу, поэтому он ищет этот класс, как указано в Разделе 9.3.5 стандарта:

Если определение функции-члена лексически выходит за пределы определения класса, имя функции-члена должно быть квалифицировано по имени класса с помощью оператора ::.[Примечание: имя, используемое в определении функции-члена (то есть в условии объявления-параметра, включая аргументы по умолчанию (8.3.6), или в теле функции-члена, или, для функции конструктора (12.1), ввыражение mem-initializer (12.6.2)) ищется, как описано в 3.4.] [Пример:

struct X {
    typedef int T; 
    static T count; 
    void f(T); 
}; 

void X::f(T t = count) { }

Функция-член f класса X определена в глобальной области видимости;запись X::f указывает, что функция f является членом класса X и находится в области видимости класса X.В определении функции тип параметра T относится к члену typedef T, объявленному в классе X, а число аргументов по умолчанию относится к количеству статических членов, объявленных в классе X.]

В принципе, то, что вы делаете, хорошо.Однако есть другой (предпочтительный) способ сократить беспорядок при использовании вложенных пространств имен или пространств имен с длинными именами (или обоими) - определить псевдоним:

namespace short_name = averylong::nested::namespacename;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...