我正在研究Bjarne Stroustrup的“ C编程语言(第4版)”,并且在14.4.6节(命名空间-版本)中遇到了一个无法复制的示例。示例#include
将一个命名空间的类声明放入另一个命名空间。这是我简化的重现此示例的尝试:
// V3.h
namespace V3 {
class C {
public:
void print();
};
}
// V3.cpp
#include <iostream>
#include "V3.h"
using namespace std;
namespace V3 {
void C::print() {
cout << "Hello from C" << endl;
}
}
// Popular.h
namespace Popular {
#include "V3.h"
}
// main.cpp
#include "Popular.h"
int main() {
Popular::V3::C c;
c.print();
}
当我尝试编译该程序时,得到以下输出:
$ g++ main.cpp V3.cpp
/tmp/ccAVnUZi.o: In function `main':
main.cpp:(.text+0x1f): undefined reference to `Popular::V3::C::print()'
collect2: error: ld returned 1 exit status
因此,我想知道,是否可以#include
将一个命名空间的类转换为另一个命名空间?还是我由于其他原因未能重现此示例?我在下一节(15.2.5)中读到,可能无法执行此操作。
答案 0 :(得分:1)
是的,这是完全可能的(尽管存在很大疑问)。 #include
实际上只是文本复制粘贴。就好像您的Popular.h
是:
namespace Popular {
namespace V3 {
class C {
public:
void print();
};
}
}
这恰好是合法的C ++代码,当然在很多情况下不是这样。
请注意,此类C
是::Popular::V3::C
。这与V3.h
中声明的类型(::V3::C
)不同且无关。第二种类型在print()
中为其V3.cpp
函数定义。
但这不是您要调用的print()
-您正在调用::Popular::V3::C::print()
(这又是与::V3::C
不同类型的成员函数)并且没有定义在任何地方使用此功能。因此,结果是得到一个undefined reference-您需要为此添加一个定义。像这样说:
// Popular.cpp
#include <iostream>
void Popular::V3::C::print() {
std::cout << "This is bad and I should feel bad about it. :-(" << std::endl;
}
但是,实际上,除非您有非常有说服力的理由,否则不要#include
内的东西namespace
。您可以改为提供名称空间别名:
#include "V3.h"
namespace Popular {
namespace V3 = ::V3;
}
这将使您仍然写Popular::V3::C
,现在它实际上与::V3::C
相同。
或类型别名:
#include "V3.h"
namespace Popular {
using C = ::V3::C;
}
这里::Popular::C
实际上与::V3::C
的类型相同。