是否可以将包含名称空间的类包含到另一个名称空间中

时间:2019-04-19 00:37:08

标签: c++ c++11 namespaces include

我正在研究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)中读到,可能无法执行此操作。

1 个答案:

答案 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的类型相同。