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

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

概述通过我的一个项目,我将进入C领域.基本上我来了 来自 Java背景,并想知道 Java包的概念如何 在C世界中实现.这使我进入了命名空间的C概念. 到目前为止,我对命名空间完全没问题,但是当涉及到头文件时 在完全合格的课程方面,事情变得低效 名称,使用指令和使用声明. 关于这个问题的一个很好的描述是Herb Sutter的this文章. 据我所知,这一切归结为:如果你总是写一个头文件 使用完全限定 通过我的一个项目,我将进入C领域.基本上我来了
来自 Java背景,并想知道 Java包的概念如何
在C世界中实现.这使我进入了命名空间的C概念.

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

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

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

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

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

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

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

MyFirstClass.hpp

#ifndef MYFirsTCLASS_HPP_#define MYFirsTCLASS_HPP_namespace com {namespace company {namespace package1 {class MyFirstClass{public:    MyFirstClass();    ~MyFirstClass();private:};} // namespace package1} // namespace company} // namespace com#endif /* MYFirsTCLASS_HPP_ */

MyFirstClass.cpp

#include "MyFirstClass.hpp"using com::company::package1::MyFirstClass;MyFirstClass::MyFirstClass(){}MyFirstClass::~MyFirstClass(){}

MySecondClass.hpp

#ifndef MYSECONDCLASS_HPP_#define MYSECONDCLASS_HPP_#include <string>#include "MyFirstClass.hpp"namespace com {namespace company {namespace package2 {    /*     * Do not write using-declarations in header files according to     * Herb Sutter's namespace Rule #2.     *     * using std::string; // bad     * using com::company::package1::MyFirstClass; // bad     */class MySecondClass{public:    /*     * Public class-scoped typedefs instead of using-declarations in     * namespace package2. Consequently we can avoID fully qualifIEd     * type names in the remainder of the class declaration. This     * yIElds maximum readability and shows cleanly the types imported     * from other namespaces.     */    typedef std::string String;    typedef com::company::package1::MyFirstClass MyFirstClass;    MySecondClass();    ~MySecondClass();    String getText() const; // no std::string required    voID setText(String as_text); // no std::string required    voID setMyFirstInstance(MyFirstClass anv_instance); // no com::company:: ...    MyFirstClass getMyFirstInstance() const; // no com::company:: ...private:    String is_text; // no std::string required    MyFirstClass inv_myFirstInstance; // no com::company:: ...};} // namespace package2} // namespace company} // namespace com#endif /* MYSECONDCLASS_HPP_ */

MySecondClass.cpp

#include "MySecondClass.hpp"/* * According to Herb Sutter's "A Good Long-Term Solution" it is fine * to write using declarations in a translation unit,as long as they * appear after all #includes. */using com::company::package2::MySecondClass; // OK because in cpp file and                                             // no more #includes followingMySecondClass::MySecondClass(){}MySecondClass::~MySecondClass(){}/* * As we have already imported all types through the class scoped typedefs * in our header file,we are Now able to simply reuse the typedef types * in the translation unit as well. This pattern shortens all type names * down to a maximum of "Classname::TypedefTypename" in the translation unit - * e.g. below we can simply write "MySecondClass::String". At the same time the * class declaration in the header file Now governs all type imports from other * namespaces which again enforces the DRY - Don't Repeat Yourself - principle. */// Simply reuse typedefs from MySecondClassMySecondClass::String MySecondClass::getText() const{    return this->is_text;}// Simply reuse typedefs from MySecondClassvoID MySecondClass::setText(String as_text){    this->is_text = as_text;}// Simply reuse typedefs from MySecondClassvoID MySecondClass::setMyFirstInstance(MyFirstClass anv_instance){    this->inv_myFirstInstance = anv_instance;}// Simply reuse typedefs from MySecondClassMySecondClass::MyFirstClass MySecondClass::getMyFirstInstance() const{    return this->inv_myFirstInstance;}

Main.cpp的

#include <cstdio>#include "MySecondClass.hpp"using com::company::package2::MySecondClass; // OK because in cpp file and                                             // no more #includes followingint main(){    // Again MySecondClass provIDes all types which are imported from    // other namespaces and are part of its interface through public    // class scoped typedefs    MySecondClass *lpnv_mySeccls = new MySecondClass();    // Again simply reuse typedefs from MySecondClass    MySecondClass::String ls_text = "Hello World!";    MySecondClass::MyFirstClass *lpnv_myFirClsf =            new MySecondClass::MyFirstClass();    lpnv_mySeccls->setMyFirstInstance(*lpnv_myFirClsf);    lpnv_mySeccls->setText(ls_text);    printf("Greetings: %s\n",lpnv_mySeccls->getText().c_str());    lpnv_mySeccls->setText("Goodbye World!");    printf("Greetings: %s\n",lpnv_mySeccls->getText().c_str());    getchar();    delete lpnv_myFirClsf;    delete lpnv_mySeccls;    return 0;}
解决方法 通过降低复杂性来缓解疼痛.你正在把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头文件的命名空间邪恶?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1236119.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存