行外のメンバー関数定義にグローバルスコープまでの完全修飾クラス名が必要ですか?


14

この質問で、クラス外のメンバー関数定義でクラス名(グローバルスコープ演算子を含む)を完全に修飾することが有用/必要であるかどうか疑問に思いました。

一方では、これが以前に行われたのを見たことがありません(適切に行うための構文は不明瞭に思われます)。もう1つは、C ++の名前検索は非常に簡単ではないため、コーナーケースが存在する可能性があります。

質問:

クラス外のメンバー関数定義の導入
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }

ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... }(グローバルスコープ::プレフィックスなし)と異なる場合はありますか?

メンバー関数の定義は、クラスを囲む名前空間に配置する必要があるため、これは有効な例ではありません。


反対投票者がこの質問について嫌いなことは非常に好奇心が強い。フィードバックを歓迎します!
Max Langhof

定義が宣言とは異なる名前空間に配置された場合?それは、あなたがリンクする
クエシトン

おっと、細字を読みませんでした;)
idclev 463035818

@ formerlyknownas_463035818それも私が考えていたものであり、それを試してみて機能しないことに気づいたので、質問を書きました(他の人も不思議に思うだろう)。
Max Langhof

回答:


12

A -ディレクティブを使用しては発生する可能性があります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)() {
   }
} 

もちろん、2番目のオーバーロードをfoo::foo::bar::bazグローバルスコープのように書くこともできますが、問題は、2つの宣言が異なる意味を持つことができるかどうかでした。そのようなコードを書くことはお勧めしません。


はい、これは確かに有効な回答であり、を必要とすることすらありませんusing。さまざまなケースを強調表示しておくと便利です。
Max Langhof

2

usingディレクティブを使用すると、混乱を招くコードが存在する可能性があります。

次の実証プログラムを検討してください

#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"; }

関数が宣言されている場所を正確に示します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.