Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 实现或定义在未命名/匿名命名空间中声明的类或函数_C++_Namespaces_Implementation - Fatal编程技术网

C++ 实现或定义在未命名/匿名命名空间中声明的类或函数

C++ 实现或定义在未命名/匿名命名空间中声明的类或函数,c++,namespaces,implementation,C++,Namespaces,Implementation,在未命名(匿名)命名空间之外定义函数或类成员的实现是否合法。 我的编译器接受它,但我想确定它是合法的 e、 g 原因是我希望避免我们的未锈蚀格式造成不必要的缩进 #include <iostream> using namespace std; namespace { struct X { X(int); int x_; }; } X::X(int x) : x_(x) {} int main() { X x(5); cout <

在未命名(匿名)命名空间之外定义函数或类成员的实现是否合法。 我的编译器接受它,但我想确定它是合法的 e、 g

原因是我希望避免我们的未锈蚀格式造成不必要的缩进
#include <iostream>
using namespace std;

namespace
{
  struct X
  {
     X(int);
     int x_;
  };
}

X::X(int x) : x_(x) {}

int main()
{
   X x(5);

   cout << x.x_ << "\n";
   return 0;
}
使用名称空间std; 名称空间 { 结构X { X(int); int x_2;; }; } X::X(int X):X_ux(X){} int main() { X(5);
cout它实际上与以下内容没有什么不同,这是完全合法的:

namespace ns {
    struct s {
        void f();
    };
}

using namespace ns;

void s::f() { }

命名名称空间中的名称被引入全局名称空间,因此可以在那里为它们提供定义。与未命名名称空间的唯一区别是它没有名称(实际上,它有一些唯一的、无法表达的名称)使用名称空间的
是隐式的。

是的。这是完全合法的。未命名名称空间的区别在于,名称空间的内容仅在其声明的文件中可用。如果它位于
.h
文件中,则它将添加到所有后续的
.cpp
文件和每个
.cpp
文件中l具有
命名空间
内容的唯一副本

事实上,声明全局
静态
变量是一种更好的方法。现在看看,它会产生什么样的影响:

namespace {
 struct X
 {
   void foo(int x);
 };
 int i;  // declare this global variable
}
如果将此代码放在头文件中,则无论该头文件位于哪里,只要该头文件是
#include
ed,所有
.cpp
文件都将在其内部有一个不同的
int i;
副本。在一个
.cpp
文件中更改
i
的值不会影响另一个
.cpp
文件


此外,对于多个定义,它不会给出链接器错误,因为它位于未命名的
命名空间中

编辑:要对其进行更多评估,请按以下方式定义命名空间:

// x.h
namespace
{
  struct X
  {
    void foo(int x)
    {
      static int c;  // static inside the function
      cout<<"a = "<<(c++)<<endl;
    }
  };
}
这意味着
.cpp
两个文件中的
X::foo()
是不同的。如果给
名称空间
一个名称并重复相同的操作,它将输出

a = 0
a = 1

因此,未命名的
名称空间
为每个翻译单元创建不同的副本。

在您的场景中是合法的,但在一个场景中,它将导致编译器出现不明确的错误

如果在X.h中有另一个类:

// X.h
struct X
{
    void foo(int x) { }
};
在foo.cpp中,需要使用X.h中定义的X

////////////////
// foo.cpp 
#include "X.h"

namespace {
    struct X
    {
        void foo(int x);
    };

    // use the X declared in anonymous namespace
    void test()
    {
        X x;
        x.foo(3);
    }
}

// reference to 'X' is ambiguous
void X::foo(int x)
{
}

void otherFunction()
{
    // Use struct X in X.h
    ::X x;
    x.foo(3);
}

如果将实现代码保留在匿名名称空间之外,编译器会抱怨不明确。如果将实现代码移到匿名名称空间内,效果会很好。

我认为(但我不是100%)匿名名称空间本身不是名称空间(所以您可以声明),它只意味着在其中声明了实例(变量和函数)具有静态链接,即它们是翻译单元的本地。@Kerrek:据我所知,它们实际上是名称空间,每个翻译单元有不同的名称。它们的行为类似于:
namespace{/*…*/}使用namespace;
所以像Koenig查找这样的规则也应该适用于它们。@smerlin:对,除了不清楚的名称查找原因之外,它实际上相当于使用namespace unique\u name;namespace unique\u name{/*内容放在这里*/}
@smerlin:我明白了-所以它确实会影响声明?那么
X
的完全限定名是什么?@Kerrek:在未命名名称空间中声明的名称实际上可能有外部链接。这并不重要,因为无法从另一个翻译单元引用它们(唯一的名称不可用)。这是不正确的,两者可用于不同的目的。您不能在命名的
命名空间中定义全局变量,但在未命名的
命名空间中可以定义全局变量。当在.h文件中声明未命名的
命名空间时,它会为
.cpp
文件中包含的所有定义创建唯一副本。未命名的
名称pace
为每个翻译单元生成其中定义的所有变量的唯一副本;命名的
名称空间
无法做到这一点。我已编辑了我的答案以了解更多详细信息。@iammilind:是的,这直接源于以下事实:未命名的名称空间在每个翻译单元中具有不同的名称,这意味着在未命名命名空间在每个转换单元中具有不同的完全限定名。
// X.h
struct X
{
    void foo(int x) { }
};
////////////////
// foo.cpp 
#include "X.h"

namespace {
    struct X
    {
        void foo(int x);
    };

    // use the X declared in anonymous namespace
    void test()
    {
        X x;
        x.foo(3);
    }
}

// reference to 'X' is ambiguous
void X::foo(int x)
{
}

void otherFunction()
{
    // Use struct X in X.h
    ::X x;
    x.foo(3);
}