我有一个Main.cpp和Example.cpp文件。
这可能是我做的很糟糕,因为我是c ++的新手,但这里是我在Example.cpp中写的代码:
#include <iostream>
namespace example {
using namespace std;
void myfunc1() {
cout << "func1" << endl;
}
void myfunc2() {
cout << "func2" << endl;
}
}
所以,我想到了在Main.cpp中调用该命名空间:
#include <iostream>
using namespace example;
int main() {
return 0;
}
现在我有一个问题要打电话&#34;示例&#34;另一个文件的命名空间我是否需要为该cpp文件创建标题?
答案 0 :(得分:3)
这是你应该怎么做的。您应该在单个头文件中声明要包含在命名空间中的函数,然后将其包含在需要它的每个cpp文件中。 您的&#34;命名空间&#34;的实现函数也应该在一个cpp文件中。 在您的示例中,这应该如下。
example.hh:
#ifndef __EXAMPLE_HH__
# define __EXAMPLE_HH__
namespace example
{
void myfunc1();
void myfunc2();
}
#endif
example.cpp:
#include <iostream>
#include "example.hh"
void example::myfunc1()
{
std::cout << "func1" << std::endl;
}
void example::myfunc2()
{
std::cout << "func2" << std::endl;
}
声明并实现您的示例命名空间后,您可以按照以下方式使用它:
main.cpp:
#include "example.hh"
int main()
{
example::myfunc1();
example::myfunc2();
return (0);
}
请注意,我没有使用using namespace
语句,这就是为什么我需要在我的函数名称之前写example::
的原因。
如果您不想每次都写example::
,可以编写using namespace example
但要小心:它不允许您省略#include "example.hh"
预处理程序指令,否则编译器甚至不知道你的example
名称空间存在。
请记住:using namespace
并不代表#include
指令。
关于源文件和头文件的说明。
在该示例中,您有3个文件:1个头文件(example.hh)和2个源文件(example.cpp,main.cpp)。 在头文件中声明命名空间,类,结构,函数...是常见的(因为有用),并在每个源文件中包含此头文件需要使用之前定义的名称之一。
为什么?允许编译器知道这些名称。在这里,为了使您成为可执行文件,有两个步骤:
步骤1:将每个源文件编译为相应的目标文件,即从example.o
文件中生成example.cpp
文件。 example.o
文件将包含字节代码(此处为example::myfunc1
和example::myfunc2
函数的代码)和main.o
main
函数的代码。< / p>
这些目标文件由编译器生成。例如,您使用GCC(G ++ for C ++)创建一个目标文件,如下所示:g++ -c -o example.o example.cpp
。
这里的头文件很有用。当GCC读取您的example.cpp
文件时,GCC会读取#include "example.hh"
语句,告诉他也要阅读example.hh
,以及GCC如何了解您的命名空间及其功能
example.cpp
,如果您没有包含头文件,GCC会读取void example::myfunc1() { ... }
并且根据您使用的编译器,您会抛出错误告诉您类似Unknown namespace
的内容main.cpp
,您可能会收到另一个错误,告诉您找不到命名空间。有趣的是,在编译main.o
中,字节代码粗略地表示call myfunc1 from the example namespace, then call myfunc2 from the example namespace
,但 DOES NOT 包含这两个函数的代码在main.o
档案中。
因此,当GCC读取函数调用时,它不知道它们的实现,但它从头文件中知道它们。粗略地说,在头文件中声明它们并将其包含在源文件中告诉GCC类似This namespace and its functions exist, they will be implemented somewhere else
。
所以在这里,你有2个相应的目标文件:main.o
和example.o
。
第2步:获取您刚刚创建的所有目标文件以链接它们并生成可执行文件。再次,GCC:gcc -o exampleExcutable main.o example.o
。魔术发生的地方:链接器看到有example::myfunc1
和example::myfunc2
的调用,在example.o
找到它们的实现,并且能够创建你的可执行文件文件
在这里,您可以获得可执行文件exampleExecutable
,然后运行它并获得预期的输出:
$ ./exampleExecutable
func1
func2
要实现,头文件用于声明符号并包含在源文件中。编译源文件时,相应的目标文件不包含这些声明符号的定义,但它们会在链接时解析。
答案 1 :(得分:1)
为了让编译器/链接器知道你所指的是哪个函数,它需要函数的原型。
为您的名称空间创建标题,例如
#ifndef EXAMPLE_H
#define EXAMPLE_H
namespace example
{
void myfunc1();
void myfunc2();
};
#endif
然后在example.cpp和main.cpp
中包含标题