是否在C++命名空间中声明的函数,但在其外部定义的函数将从该命名空间保留类型?

是否在C++命名空间中声明的函数,但在其外部定义的函数将从该命名空间保留类型?,c++,namespaces,C++,Namespaces,我指的是Stroustrup在3.3名称空间中的“C++之旅”的一个稍微模糊的例子。他举了以下例子: namespace My_Code { class complex { /* ... */ }; // class complex is within My_Code scope complex sqrt(complex); //takes our locally-defined complex as an argument int main(); } // D

我指的是Stroustrup在3.3名称空间中的“C++之旅”的一个稍微模糊的例子。他举了以下例子:

namespace My_Code {
    class complex { /* ... */ };  // class complex is within My_Code scope

    complex sqrt(complex); //takes our locally-defined complex as an argument

    int main(); 
}

// Defining My_Code main function *outside* of the My_Code namespace,
// but this is fine
int My_Code::main() {
    complex z {1, 2};   // My_Code::complex, or std::complex?
    auto z2 = sqrt(z);  // My_Code::sqrt(), or std::sqrt()?
    std::cout << '{' << z2.real() << ',' << z2.imag() << "}\n";
    // ...
}

int main() {
    return My_Code::main();
}

我的问题是:尝试了这一点,发现预期的类型来自我的_代码,为什么在这种情况下z和z2的类型属于我的_代码?当然,如果我们在名称空间之外定义这个函数,那么我们就不再在没有限定的情况下使用我们自己的类型,我们应该限定它们吗?或者,我们从特定名称空间实现函数的事实是否解释了这种行为?

这是为了一致性。考虑:

namespace N
{
    struct S
    {
         int f();
    private:
         int g();
         int x;
    };
    int h(int);

    int S::f()
    {
        // member of N::S, therefore not only finds N::S::g() during lookup
        // but has access to private member
        g();
    }
}

int N::S::g()
{
    // member of N::S, therefore finds and has access to N::S::x
    // wouldn't it be weird if it could access members of the class but
    // not its enclosing namespace?
    // therefore it also can lookup N::h()
    return h(x);
}

int N::h(int a)
{
    // member of N, therefore can lookup N::S
    //        just like N::S::g() can find N::h()
    S s;
    return a;
}

成员函数的类外定义可以在类和封闭作用域中进行查找,如果命名空间成员的查找不正确,则会出现一种非常奇怪的情况,即命名空间成员对外部定义的命名空间的函数可见,这取决于它们是否为类成员函数。这真是令人困惑。

这是为了一致性。考虑:

namespace N
{
    struct S
    {
         int f();
    private:
         int g();
         int x;
    };
    int h(int);

    int S::f()
    {
        // member of N::S, therefore not only finds N::S::g() during lookup
        // but has access to private member
        g();
    }
}

int N::S::g()
{
    // member of N::S, therefore finds and has access to N::S::x
    // wouldn't it be weird if it could access members of the class but
    // not its enclosing namespace?
    // therefore it also can lookup N::h()
    return h(x);
}

int N::h(int a)
{
    // member of N, therefore can lookup N::S
    //        just like N::S::g() can find N::h()
    S s;
    return a;
}
成员函数的类外定义可以在类和封闭作用域中进行查找,如果命名空间成员的查找不正确,则会出现一种非常奇怪的情况,即命名空间成员对外部定义的命名空间的函数可见,这取决于它们是否为类成员函数。这真的很让人困惑。

正如标准所说的那样,因为标准是这么说的。对于My_Code::和右大括号之间的所有内容,名称查找从My_Code开始

int My_Code::main定义函数main的类型为int,并且驻留在名称空间My_Code中。这意味着My_代码中的功能可以使用。因此,类型z和z2属于My_代码。

As,因为标准如此规定。对于My_Code::和右大括号之间的所有内容,名称查找从My_Code开始


int My_Code::main定义函数main的类型为int,并且驻留在名称空间My_Code中。这意味着My_代码中的功能可以使用。因此,类型z和z2属于My_代码。

查找ADL:因为标准上这么说。对于My_Code::和右大括号之间的所有内容,名称查找从My_Code开始。此外,您不包括任何标准头-为什么您甚至希望声明std::complex。更不用说找到了?@IgorTandetnik我只是引用了书中的例子。在我用来测试的代码中,我包含了复杂的标题。事实证明,这并不是必须的。@Quimby:ADL与此无关。我相信int My_Code::func{bla}与名称空间My_Code{int func{bla}相同,因为标准是这样说的。对于My_Code::和右大括号之间的所有内容,名称查找从My_Code开始。此外,您不包括任何标准头-为什么您甚至希望声明std::complex。更不用说找到了?@IgorTandetnik我只是引用了书中的例子。在我用来测试的代码中,我包含了复杂的标题。事实证明,这不是必须的。@Quimby:ADL与此无关。我相信int My_Code::func{bla}与名称空间My_Code{int func{bla}相同因此,我认为考虑类外定义和更普遍的名称空间外定义的方法是,我们这样做是出于表示与定义分离等原因,但就编译器而言,它们可以访问的范围没有变化?@DanielSoutar:正确。此外,类内定义会自动添加内联关键字,因此类外定义有助于避免这种情况。因此,我认为考虑类外定义和更普遍的命名空间外定义的方法是,我们这样做是出于表示与定义分离等原因,但就编译器而言,他们访问的范围没有变化?@DanielSoutar:正确。此外,类内定义会自动添加inline关键字,因此类外定义有助于避免这种情况。