In one of my projects I will enter the C ++ field. I mostly go from the Java background and wondered how the concept of Java packages is implemented in the C ++ world. This led me to the concept of C ++ namespaces.
I still have a good understanding of namespaces, but when it comes to header files everything becomes ineffective with regard to a fully qualified class of names, directives, and declarations.
A very good description of the problem is this article by Herb Sutter.
As I understand it, it all boils down to: if you are writing a header file always use full type names to refer to types from other namespaces.
This is almost unacceptable. Since the C ++ header usually provides a class declaration, maximum readability is of utmost importance. Fully qualifying each type from a different namespace creates a lot of visual noise, finally reducing the readability of the header to such an extent that it raises the question of whether to use namespaces at all.
However, I want to use C ++ namespaces and so the question is: How to overcome the slander of the C ++ header file namespace? After some research, I think that typedefs can be an effective way to solve this problem.
After that, you will find an example C ++ program that demonstrates how I will, for example, use types of typed types with an open class to import types from other namespaces. The program is syntactically correct and compiles on MinGW W64. So far so good, but I'm not sure if this approach happily removes the using keyword from the header, but brings another problem that I just don't know about. Just something complicated, like the things described by Herb Sutter.
I ask everyone who has a complete understanding of C ++, check out the code below and let me know if this should work or not. thanks for your thoughts.
MyFirstClass.hpp
#ifndef MYFIRSTCLASS_HPP_ #define MYFIRSTCLASS_HPP_ namespace com { namespace company { namespace package1 { class MyFirstClass { public: MyFirstClass(); ~MyFirstClass(); private: }; }
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 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 "A Good Long-Term Solution" it is fine * to write using declarations in a translation unit, as long as they * appear after all
main.cpp
#include <cstdio> #include "MySecondClass.hpp" using com::company::package2::MySecondClass; // OK because in cpp file and // no more #includes following int 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; }