如何克服C头文件的命名空间邪恶?

前端之家收集整理的这篇文章主要介绍了如何克服C头文件的命名空间邪恶?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
通过我的一个项目,我将进入C领域.基本上我来了
来自 Java背景,并想知道 Java包的概念如何
在C世界中实现.这使我进入了命名空间的C概念.

到目前为止,我对命名空间完全没问题,但是当涉及到头文件
在完全合格的课程方面,事情变得低效
名称,使用指令和使用声明.

关于这个问题的一个很好的描述是Herb Sutter的this文章.

据我所知,这一切归结为:如果你总是写一个头文件
使用完全限定类型名称来引用其他名称空间中的类型.

这几乎是不可接受的.由于C头通常提供声明
在一个类中,最大可读性具有最高优先级.完全符合条件
最后,来自不同命名空间的类型会产生很多视觉噪音
标题的可读性降低到提出问题的程度
是否要使用名称空间.

不过我想利用C命名空间,所以考虑一下
问题:如何克服C头文件的命名空间邪恶?后
一些研究我认为typedef可能是解决这个问题的有效方法.

下面你将找到一个C示例程序,它演示了我的意思
喜欢使用公共类作用域typedef从其他名称空间导入类型.
该程序在语法上是正确的,并在MinGW W64上编译良好.到目前为止
很好,但我不确定这种方法是否会愉快地删除using关键字
标题但引入另一个我根本不知道的问题.
就像Herb Sutter描述的东西一样棘手.

那是我恳请所有对C有透彻了解的人
检查下面的代码,让我知道这是否有效.谢谢
为了你的想法.

MyFirstClass.hpp

  1. #ifndef MYFIRSTCLASS_HPP_
  2. #define MYFIRSTCLASS_HPP_
  3.  
  4. namespace com {
  5. namespace company {
  6. namespace package1 {
  7.  
  8. class MyFirstClass
  9. {
  10. public:
  11. MyFirstClass();
  12. ~MyFirstClass();
  13.  
  14. private:
  15.  
  16. };
  17.  
  18. } // namespace package1
  19. } // namespace company
  20. } // namespace com
  21.  
  22. #endif /* MYFIRSTCLASS_HPP_ */

MyFirstClass.cpp

  1. #include "MyFirstClass.hpp"
  2.  
  3. using com::company::package1::MyFirstClass;
  4.  
  5. MyFirstClass::MyFirstClass()
  6. {
  7. }
  8.  
  9. MyFirstClass::~MyFirstClass()
  10. {
  11. }

MySecondClass.hpp

  1. #ifndef MYSECONDCLASS_HPP_
  2. #define MYSECONDCLASS_HPP_
  3.  
  4. #include <string>
  5. #include "MyFirstClass.hpp"
  6.  
  7. namespace com {
  8. namespace company {
  9. namespace package2 {
  10.  
  11. /*
  12. * Do not write using-declarations in header files according to
  13. * Herb Sutter's Namespace Rule #2.
  14. *
  15. * using std::string; // bad
  16. * using com::company::package1::MyFirstClass; // bad
  17. */
  18.  
  19. class MySecondClass{
  20.  
  21. public:
  22. /*
  23. * Public class-scoped typedefs instead of using-declarations in
  24. * namespace package2. Consequently we can avoid fully qualified
  25. * type names in the remainder of the class declaration. This
  26. * yields maximum readability and shows cleanly the types imported
  27. * from other namespaces.
  28. */
  29. typedef std::string String;
  30. typedef com::company::package1::MyFirstClass MyFirstClass;
  31.  
  32. MySecondClass();
  33. ~MySecondClass();
  34.  
  35. String getText() const; // no std::string required
  36. void setText(String as_text); // no std::string required
  37.  
  38. void setMyFirstInstance(MyFirstClass anv_instance); // no com::company:: ...
  39. MyFirstClass getMyFirstInstance() const; // no com::company:: ...
  40.  
  41. private:
  42. String is_text; // no std::string required
  43. MyFirstClass inv_myFirstInstance; // no com::company:: ...
  44. };
  45.  
  46. } // namespace package2
  47. } // namespace company
  48. } // namespace com
  49.  
  50. #endif /* MYSECONDCLASS_HPP_ */

MySecondClass.cpp

  1. #include "MySecondClass.hpp"
  2.  
  3. /*
  4. * According to Herb Sutter's "A Good Long-Term Solution" it is fine
  5. * to write using declarations in a translation unit,as long as they
  6. * appear after all #includes.
  7. */
  8. using com::company::package2::MySecondClass; // OK because in cpp file and
  9. // no more #includes following
  10. MySecondClass::MySecondClass()
  11. {
  12. }
  13.  
  14. MySecondClass::~MySecondClass()
  15. {
  16. }
  17.  
  18. /*
  19. * As we have already imported all types through the class scoped typedefs
  20. * in our header file,we are now able to simply reuse the typedef types
  21. * in the translation unit as well. This pattern shortens all type names
  22. * down to a maximum of "ClassName::TypedefTypeName" in the translation unit -
  23. * e.g. below we can simply write "MySecondClass::String". At the same time the
  24. * class declaration in the header file now governs all type imports from other
  25. * namespaces which again enforces the DRY - Don't Repeat Yourself - principle.
  26. */
  27.  
  28. // Simply reuse typedefs from MySecondClass
  29. MySecondClass::String MySecondClass::getText() const
  30. {
  31. return this->is_text;
  32. }
  33.  
  34. // Simply reuse typedefs from MySecondClass
  35. void MySecondClass::setText(String as_text)
  36. {
  37. this->is_text = as_text;
  38. }
  39.  
  40. // Simply reuse typedefs from MySecondClass
  41. void MySecondClass::setMyFirstInstance(MyFirstClass anv_instance)
  42. {
  43. this->inv_myFirstInstance = anv_instance;
  44. }
  45.  
  46. // Simply reuse typedefs from MySecondClass
  47. MySecondClass::MyFirstClass MySecondClass::getMyFirstInstance() const
  48. {
  49. return this->inv_myFirstInstance;
  50. }

Main.cpp的

  1. #include <cstdio>
  2. #include "MySecondClass.hpp"
  3.  
  4. using com::company::package2::MySecondClass; // OK because in cpp file and
  5. // no more #includes following
  6. int main()
  7. {
  8. // Again MySecondClass provides all types which are imported from
  9. // other namespaces and are part of its interface through public
  10. // class scoped typedefs
  11. MySecondClass *lpnv_mySecCls = new MySecondClass();
  12.  
  13. // Again simply reuse typedefs from MySecondClass
  14. MySecondClass::String ls_text = "Hello World!";
  15. MySecondClass::MyFirstClass *lpnv_myFirClsf =
  16. new MySecondClass::MyFirstClass();
  17.  
  18. lpnv_mySecCls->setMyFirstInstance(*lpnv_myFirClsf);
  19.  
  20. lpnv_mySecCls->setText(ls_text);
  21. printf("Greetings: %s\n",lpnv_mySecCls->getText().c_str());
  22.  
  23. lpnv_mySecCls->setText("Goodbye World!");
  24. printf("Greetings: %s\n",lpnv_mySecCls->getText().c_str());
  25.  
  26. getchar();
  27.  
  28. delete lpnv_myFirClsf;
  29. delete lpnv_mySecCls;
  30.  
  31. return 0;
  32. }

解决方法

通过降低复杂性来缓解疼痛.你正在把C变成Java. (这与尝试其他方式一样糟糕.)

一些提示

>删除“com”命名空间级别. (这只是一个你不需要的java-ism)
>删除“company”命名空间,可以替换为“product”或“library”命名空间(即boost,Qt,OSG等).只需挑选一些独特的东西w.r.t.您正在使用的其他库.
>您不需要完全声明您所在的名称空间中的名称(请注意:模板分类,请参阅注释).只需避免在标头中使用任何名称空间指令. (并且在C文件中小心使用,如果有的话.首选内部函数.)
>考虑命名空间别名(在functions / cpp文件中),即namespace bll = boost :: lambda;.这会创建非常简洁的快捷方式.
>此外,通过使用pimpl模式隐藏私有成员/类型,您的标头显示的类型较少.

P.S:感谢@KillianDS在评论中提供了一些很好的提示(当我将它们编辑到问题中时,这些提示删除了.)

猜你在找的C&C++相关文章