如何解决C ++命名空间成员在不同文件中的访问方式如何?如何实现“命名空间标准”?
| 我在sample.h中声明了以下名称空间// namespace with identifier
namespace N1
{
int b = 80;
}
sample1.cpp使用上面的名称空间声明
#include <iostream>
#include \"sample.h\"
using namespace std;
using namespace N1;
int main(void)
{
cout << \"b (in main) = \" << b << endl;
foo(); //written in sample2.cpp
return 0;
}
sample2.cpp也使用sample.h中声明的名称空间
#include <iostream>
#include \"sample.h\"
using namespace std;
using namespace N1;
void foo(void)
{
cout << \"b = \" << b << endl;
}
当我编译时,出现以下错误
$> g++ sample1.cpp sample2.cpp
/tmp/ccB25lEF.o:(.data+0x0): multiple definition of `N1::b\'
/tmp/cchLecEj.o:(.data+0x0): first defined here
让我知道如何解决以及如何实现“命名空间标准”来避免此问题?
解决方法
包含保护仅在编译时有效,但错误发生在链接时。这是因为sample.h包含在两个编译单元中,并且在两个编译单元中都创建了变量
N1::b
。
如果您确实想要一个变量(不是const
),则必须在标头中将其声明为extern
,并在单独的编译单元中为其创建存储位置:
// sample.h
#ifndef N1
#define N1
namespace N1 {
extern int b;
}
#endif
// sample.cpp
#include \"sample.h\"
namespace N1 {
int b = 80;
}
,这不是ѭ8守卫的问题。
在头文件中使用ѭ6表示:
//sample.h
namespace N1
{
extern int b; //extern is MUST!
//DONT WRITE : extern int b = 80;
}
然后在.cpp文件中将其定义为:
//sample.cpp
namespace N1
{
int b = 80; //initialization should be here
}
,是否只是在sample.h文件中丢失了ifdef或pragma的情况?
,每次将#sample.h包含在.cpp模块中时,都会为b创建一个新的链接器记录,从而为link [1]提供多个定义。
应该在sample.cpp或其他地方定义int,并简单地在sample.h中将int b终止。
[1]一些链接器将忽略此链接,您将可以链接OK,但是大多数情况下,它将生成错误。
,您的问题是,您在一个头文件中定义了一个具有外部链接的对象,该文件包含在两个单独的编译单元中。该问题与命名空间本身无关。
一种解决方案是使头文件仅包含声明(例如,参见下文),然后将定义放在单个源文件上。
// sample.h
namespace N1
{
extern int b;
}
// sample.cc
namespace N1
{
int b = 80;
}
另一个解决方案是赋予对象内部链接,尽管这将意味着您有多个名为“ 13”的对象,但这可能不是问题。例如,如果假定b
是常数,则这将起作用,因为默认情况下const
个对象具有内部链接。
// sample.h
namespace N1
{
const int b = 80;
}
,如果您只想定义一个常量,请尝试以下方法:
namespace N1
{
enum MyEnum
{
b = 80
};
}
对于几乎所有.h文件,包含保护都是一个好主意,但是在这里,它们可能不是您的问题。最重要的一个定义规则有两个主要部分:第一个部分说每个符号只能在每个翻译单元(通常是.cpp文件)中定义一次。这就是include防护的作用:它们防止将标头包含两次,这将导致在同一翻译单元(= .cpp文件)中多次定义一个符号(如N :: b)。
但是,这还不是全部。某些符号(例如类,非内联函数和某些变量定义)对于整个程序只能声明一次。这不是没有道理的:假设您允许在一个转换单元中将名为MyInt的int值定义为40,在另一个转换单元中将其定义为80:编译器将如何知道要使用哪个值?当然,您可以在每个程序中多次声明这样的符号(但每个翻译单元只能声明一次)-否则它们只能在声明它们的翻译单元中使用。但是不能在一个以上的翻译单元中定义它们。
使用枚举是避免在您的情况下必须分开声明和定义的一种简便方法(因为枚举不受“一个定义规则”的第二版约束),但是如果您确实需要(非常量)全局变量int
类型,您可以通过以下方式实现:
样本
namespace N1
{
// The extern keyword tells the compiler that this is is only
// a declaration and the variable is defined elsewhere.
extern int b;
}
sample1.cpp
#include \"sample.h\"
namespace N1
{
// This is the definition!
int b = 5;
}
void foo()
{
using namespace std;
cout<<N1:b<<endl;
}
sample2.cpp
#include \"sample.h\"
// No need to define N1::b,since it was already defined in sample1.cpp.
void bar()
{
using namespace std;
cout<<N1:b<<endl;
}
,该程序包含变量N1::b
的两个定义,而必须完全是一个。该变量必须在带有“ 6”的标头中声明,并且只能在一个源文件中定义。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。