c++ 用namespace实现java的package的功能
以前喜欢这样组织文件:
myproject/src/moduleA放moduleA的所有cpp文件
myproject/include/moduleA放moduleA的所有h文件
对moduleB.C.D...类似的处理,但是仍然容易有name clashes
最近发现在使用上述文件组织方式的情况下,用namespace给各个module命名,结合nested namespace的特性(参见c++ primer 4th edition section 17.2.2),可以实现类似java的package的特性
福啊
我做了个实验,确实是可以的,可惜的的缺憾是我用的CodeBlocks还不是很支持这样的代码组织方式(比如说代码提示啊、头文件路径提示啊之类的都会出现问题,不过GCC编译器倒是完美支持这样的文件组织方式)
我的项目组织结构:
文件结构:
http://pan.baidu.com/s/1c07xXAS
问题:
1、include指令啰嗦,必须包含完整的相对路径,例如“#include "../../include/module2/ClsA.h"”
2、header guard啰嗦,必须指明某个类所属的模块,例如“#ifndef OSSOZTELIB_MODULE1_CLSA_H”
3、cpp中的实现代码啰嗦(当然可以通过using namespace project::module指令来解决),例如把module2.ClsA.cpp改为
1 #include "../../include/module2/ClsA.h" 2 3 #include <iostream> 4 5 using namespace ossoztelib::module2; 6 7 void ClsA::dosomething() 8 { 9 std::cout << "ossoztelib.module2.ClsA.dosomething" << std::endl; 10 } 11 12 ClsA::ClsA() 13 { 14 std::cout << "ossoztelib.module2.ClsA created" << std::endl; 15 } 16 17 ClsA::~ClsA() 18 { 19 std::cout << "ossoztelib.module2.ClsA destroyed" << std::endl; 20 }
4、调用代码啰嗦(包括include指令,以及namespace的specifier(但是在没有命名冲突的情况下不会存在这个问题))
总结:
尽管有诸多问题,不过还是很好的解决了命名冲突,虽然不如java的package机制那么方便易用。
顺便提一下,header里面是绝对不能出现using指令的
代码:
main.cpp
1 #include "include/module2/ClsA.h" 2 #include "include/module1/ClsA.h" 3 4 int main() 5 { 6 ossoztelib::module1::ClsA a; 7 ossoztelib::module2::ClsA b; 8 a.dosomething(); 9 b.dosomething(); 10 return 0; 11 }
module1.ClsA.h
1 #ifndef OSSOZTELIB_MODULE1_CLSA_H 2 #define OSSOZTELIB_MODULE1_CLSA_H 3 4 namespace ossoztelib { 5 6 namespace module1 { 7 8 class ClsA 9 { 10 public: 11 ClsA(); 12 ~ClsA(); 13 void dosomething(); 14 }; 15 16 } 17 18 } 19 #endif // OSSOZTELIB_MODULE1_CLSA_H
module1.ClsA.cpp
1 #include "../../include/module1/ClsA.h" 2 3 #include <iostream> 4 5 using namespace std; 6 7 void ossoztelib::module1::ClsA::dosomething() 8 { 9 cout << "ossoztelib::module1::ClsA::dosomething()" << endl; 10 } 11 12 ossoztelib::module1::ClsA::ClsA() 13 { 14 cout << "ossoztelib::module1::ClsA::ClsA()" << endl; 15 } 16 17 ossoztelib::module1::ClsA::~ClsA() 18 { 19 cout << "ossoztelib::module1::ClsA::~ClsA()" << endl; 20 }
module2.ClsA.h
1 #ifndef OSSOZTELIB_MODULE2_CLSA_H 2 #define OSSOZTELIB_MODULE2_CLSA_H 3 4 namespace ossoztelib { 5 6 namespace module2 { 7 8 class ClsA 9 { 10 public: 11 ClsA(); 12 ~ClsA(); 13 void dosomething(); 14 }; 15 16 } 17 } 18 19 #endif // OSSOZTELIB_MODULE2_CLSA_H
module2.ClsA.cpp
1 #include "../../include/module2/ClsA.h" 2 3 #include <iostream> 4 5 using namespace std; 6 7 void ossoztelib::module2::ClsA::dosomething() 8 { 9 cout << "ossoztelib.module2.ClsA.dosomething" << endl; 10 } 11 12 ossoztelib::module2::ClsA::ClsA() 13 { 14 cout << "ossoztelib.module2.ClsA created" << endl; 15 } 16 17 ossoztelib::module2::ClsA::~ClsA() 18 { 19 cout << "ossoztelib.module2.ClsA destroyed" << endl; 20 }