Чи потрібне повне кваліфіковане ім’я класу до загального масштабу для визначення позалінійних функцій членів?


14

Це питання змусило мене замислитись про те, чи завжди корисно / необхідно повністю кваліфікувати імена класів (включаючи глобального оператора області) у визначенні функції поза класу.

З одного боку, я ніколи не бачив цього робити раніше (а синтаксис, як це правильно зробити, здається неясним). З іншого боку, пошук імен C ++ дуже нетривіальний, тому, можливо, існує кутовий випадок.

Питання:

Чи бував коли-небудь випадок, коли введення визначення функції позакласного члена
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
відрізнятиметься від
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... }(немає ::префіксу загальної області )?

Зауважте, що визначення функцій членів необхідно помістити в область імен, що охоплює клас, тому це не є дійсним прикладом.


Дуже цікаво, що споживачеві не подобається в цьому питанні. Відгуки Ласкаво просимо!
Макс Лангхоф

коли визначення розміщується в іншій області імен, ніж декларація? Це те, що я мав на увазі для питання, яке ви посилаєте
idclev 463035818

oops, didnt read the smallprint;)
idclev 463035818

@ bivlyknownas_463035818 Це теж те, що я мав на увазі, тоді я спробував це і зрозумів, що це не вийде, тому я написав питання (вважаючи, що інші теж будуть дивуватися).
Макс Лангхоф

Відповіді:


12

З допомогою директиви може призвести Fullyдо неоднозначних без кваліфікації.

namespace Foo {
    struct X {
    };
}

using namespace Foo;
struct X {
    void c();
};

void X::c() { } // ambiguous
void ::X::c() { } // OK

5

Це необхідно, якщо хтось мазохіст і любить писати подібні речі

namespace foo {
    namespace foo {
        struct bar {
            void baz();
        };
    }

   struct bar {
       void baz();
   };

   void foo::bar::baz() {
   }

   void (::foo::bar::baz)() {
   }
} 

Звичайно, можна записати друге перевантаження як foo::foo::bar::bazу глобальному масштабі, але питання полягало у тому, чи можуть ці дві декларації мати різний зміст. Я б не рекомендував писати такий код.


Так, це дійсно правильна відповідь, і навіть не потрібна відповідь using. Приємно виділяти різні випадки!
Макс Лангхоф

2

Якщо використовується директива використання, то може виникнути заплутаний код.

Розглянемо наступну показову програму

#include <iostream>
#include <string>

namespace N1
{
    struct A
    {
        void f() const;
    };      
}

using namespace N1;

void A::f() const { std::cout << "N1::f()\n"; }

struct A
{
    void f() const;
};

void ::A::f() const { std::cout << "::f()\n"; }

int main() 
{
    N1::A().f();
    ::A().f();

    return 0;
}

Тож для читабельності це кваліфікована назва

void ::A::f() const { std::cout << "::f()\n"; }

точно показує, де функція оголошена.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.