First of all, sorry for my English.
Ok, I'm working a program that performs a specific process. This process needs some classes and functions to be defined. All of them must be organized in blocks to access them.
My first idea was to work with namespaces (C++), to get something like this:
namespace LoadSystem
{
namespace ParseBlock1
{
class ClassA {...}
class ClassB {...}
class ClassC {...}
}
namespace ParseBlock2
{
class ClassA {...}
class ClassB {...}
class ClassC {...}
}
}
So, I was reading to get the best idea if this is good or not. I already have read that I must not use lots of nested namespaces, so, for my purpose, the minimum levels are two, as shown above.
My objective is to be able to add more and more ParseBlocks into the LoadSystem namespace. It will be stored in a single .h file, so, there will be only interfaces of the classes. Since there can be lots of classes per block, I want to split the definition of each block into other .h files to keep the main .h file small as I can.
So, I ended with an idea of defining a file block1.h and block2.h, each one with a structure like this:
namespace LoadSystem
{
namespace ParseBlock1
{
class ClassA {...}
class ClassB {...}
class ClassC {...}
}
}
and
namespace LoadSystem
{
namespace ParseBlock2
{
class ClassA {...}
class ClassB {...}
class ClassC {...}
}
}
And import them in the load_system.h file. So, every time I need to add another block, I write the needed files, and finally, I just import the new blockX.h into the main load_system.h.
Then, I must be able to access both blocks from the same namespace using LoadSystem::ParseBlock1::Class1 or LoadSystem::ParseBlock2::Class1.
I have tested this with simple integer values and it works. The namespaces combine and I can access the values without any warning (I used gcc -Wall -Werror -Wextra -pedantic).
So, is this combination of namespaces is correct or not. Maybe it works, but I maybe should not use it, I don't know.
Also, I want to know if this process, of importing a "master" header file (which imports other header files) is also correct or not (I'm using the needed #ifndef, #define and #endif macros to guard from multiple imports), I'm using something like this:
# ifndef LOAD_SYSTEM_H_
# define LOAD_SYSTEM_H_
# include "block1/block1.h"
# include "block2/block2.h"
# endif
So, please help me to know if this is correct or not.
You can always extend an existing namespace, so that part is OK.
And that part is the only that has a simple technical answer.
Regarding "master header file", it's more subjective, a matter of personal preference. I prefer that the included headers can be included on their own without any prerequisites (like including other stuff before them). If so, then all's OK for me, but if not, then users of your code will in practice have to include the big master header file in order to get any little smaller header, and that can affect build times negatively (and if they don't, but themselves include the prerequisites, then they have brittle code that can stop working when you update a header).
Related
I have classes that look like this:
Header (.h):
class DatabaseX ; //forward declare
class DeepClass
{
public:
void DeepClass(DatabaseX* db);
void doStuff();
private:
DatabaseX *m_db;
};
Definition (.cpp)
#include "some/path/that/stretches/into/a/rather/deep/structure/DeepClass.h"
#include "another/somewhat/disturbing/long/path/to/somewhere/distant/DatabaseX.h"
void DeepClass::DeepClass(DatabaseX* db):m_db(db){ m_db->open() }
void DeepClass::~DeepClass(){ m_db->close(); delete m_db; }
void DeepClass::doStuff(){ // <complicated stuff here> }
Now I want a test that checks that doStuff() does the right kind of stuff.
So I write my own mock DatabaseX.
But I have a problem, my own mock database lives in the test directory, it has no place in production code, and what's worse, DatabaseX was never written to be inherited and overloaded.
It's a concrete class, and isn't anything like an interface.
So my question is, how do I write a test, with all these hard-coded include paths everywhere?
Do I for example:
create another duplicate file structure that matches the include paths, and put my mock DatabaseX there in this duplicate file structure?
Somehow rewite each cpp file before the compiler accesses it by some indirection magic or other?
Add macros to eat up the paths?
Write a python/perl/bash script to temporarily remove the include paths prior to compiling my tests?
Just include everything, accept the dependencies of DatabaseX, and just compile the real thing, and all it's dependencies and then replace at link time?
Accept defeat; don't write any tests, and bury my head in the sand.
OR ... ?
I should say there are well over a million lines of code, so changing the source code isn't an option.
Is there a very simple way to overcome this nightmare via a nice simple compiler option or other?
(Perhaps it's not relevant but I'm using Qt's QTest & QtCreator. Maybe there is some magical switch that makes all these gruesome paths go away!).
I am using GCC 4.8.5
OpenVPN is a giant header only 'library'. I created a library based on it, which consists of a MyClass.h file that has a class MyClass that uses the headers from OpenVPN. I compile this library as libmy.
The problem is that when I try to use libmy in another project, I'm forced to include MyClass.h, which in turn includes all of the OpenVPN headers. I don't need them, since MyClass hides all OpenVPN-related things. However, since OpenVPN headers have some static variables like static int context_data_index (defined AND declared in header, here), these variables get duplicate definitions when I try to compile my new project.
Let me explain the problem better. This is MyClass.h:
class MyClass {
public:
//lots of 'methods' that hide OpenVPN-related things. Users of these methods dont even know about OpenVPN
private:
//Users of MyClass do not need to know about this unique_ptr, but I'm forced to show it in `MyClass.h`, which is why I get duplicated definitions
#ifndef DO_NOT_INCLUDE_OPENVPN_HEADERS
std::unique_ptr<OpenVPNClient> openVpnClient;
#endif
}
as you can see, the users of MyClass don't have to know anything about OpenVPN objects. I even tried to put an #ifndef clause that conditionally includes std::unique_ptr<OpenVPNClient> openVpnClient; when compiling libmy but does not include when compiling the library that uses libmy, but I got terrible undefined behaviour by doing that. I guess it's because a class must have the same number of objects with the same objects in both the libmy implementation and in my new library.
What can I do about this problem?
Try
namespace my_namespace
{
#include "something.h"
}
One solution to not requiring the users of your class to directly include the OpenVPN headers is to forward declare OpenVPNClient in your header for MyClass like this:
class OpenVPNClient;
For this to work your destructor for MyClass needs to be defined in your translation unit. This could be as simple as adding the following line to your source file for MyClass:
MyClass::~MyClass() = default;
There is more info on how to do this and why it is needed here:
Is std::unique_ptr<T> required to know the full definition of T?
An alternate solution is to use PIMPL with your class and completely hide the OpenVPNClient from the header. There is information on how to use PIMPL here:
https://en.cppreference.com/w/cpp/language/pimpl
In your question you asked about a solution where you used an #ifdef to hide the usage of the OpenVPNClient to users of your class but define it when building your class: I guess it's because a class must have the same number of objects with the same objects in both the libmy implementation and in my new library. You can't have 2 different definitions of the class. This will cause undefined behavior.
I've been writing some code for a while now. I've been using namespaces to separate a few parts of code to make the code more readable. However, I ran into a problem where I wanted to make something in that private. Here's what I found works:
//foobar.h
namespace foo_bar {
//Other items here...
}
//foobar.cpp
namespace foo_bar {
//Other items here...
void foo_barz() {..
//Faked private method!
}
}
It compiled fine. Is there any negative to using this method? I think a class might have been a better choice for this, but using a namespace, at the time, seemed like a simpler solution because it was all one project. Is there a more "conventional" way to do this? Is this likely to cause other issues down the road? What might some issues with this be?
EDIT: I guess I wasn't clear what I did. What I did was this: I didn't include the function prototype in the header file, so when included, the header file makes the code which the file was included into think that the function doesn't exist.
To make foo_barz really "private" (i.e. not have its name accessible from other units), place it in an anonymous namespace, not foo_bar:
// foobar.cpp
namespace /* stuff in here is only visible within this unit */
{
void foo_barz() { ...
}
If you wanted to declare that function before defining it, you could add:
namespace
{
void foo_barz();
}
because multiple unnamed namespaces in the same unit actually all refer to the same unnamed namespace.
Another way to achieve the same thing is to declare the function as static:
static void foo_barz() { ...
which may be done inside or outside of a namespace. Some people disapprove of this option (for reasons that are not clear to me).
In OOP, you want to break apart a program into multiple classes.
In C#, you would do as such:
namespace a
{
public class ClassA
{
//Methods...that are defined and have code in them.
}
}
and to use that class, you just do "using namespace a;".
Say I want to create a class in C++, and define them, and put code in them.
class ClassA
{
public:
void methodA();
}
ClassA::methodA()
{
//implementation.
}
To access this implementation, you would just use #include "ClassA.h". I fully understand that, and then you have to implement that code again? That seems counterproductive as I like to spread my project over a lot of classes.
So what would be the proper procedure to implement ClassA and not re-implement all it's methods again?
You don't have to reimplement them in each CPP file, the C++ linker takes care of making sure the definitions get matched together.
All you need is:
A header:
#ifndef FOO_H
#define FOO_H
class Foo{
//Junk goes here
};
#endif
A cpp:
#include "foo.h"
//implementations for junk goes here
void Foo::junk(){
}
And then you can include foo.h. Each cpp will be compiled to a .o file. Than, those .o files are handed to the linker which can figure out where definitions are and piece together the code correctly.
C and C++ have a different way of doing things. As long as you have a declaration for a class, method, or external variable the compiler will happily compile and leave off the actual definition of the methods, classes, etc, for link time. This is simplifying things a lot, but basically the compiler will leave a hint to the linker in the object file, saying that the linker needs to insert the address of the method here.
So you just need to include the "ClassA.h" file and you can compile fine.
Because of this you see some different behavior in C and C++ than you would in C#. For example, in C or C++ it's perfectly fine to have two different items (methods, variables, etc) that are named the same in different files as long as neither one is visible outside the file. Whereas in C# you would have to use different namespaces or different names. Note - not that I'm saying this is good practice, it's just possible.
The .h header files contain the class specification. The corresponding .cpp files contain the implementation and are compiled to .o files. During development, you would include .h files to access the APIs provided by the class. During compilation/linking stage, you would include the .o files also along with your source files to form the final binary. You don't need to implement anything again, w.r.t to the class you are using.
I am writing a utility library which is made up of several "Packages". The classes in each package are contained in various namespaces. I have an idea as to how I can simplify the situation by automatically declaring using statements at the end of class declarations (see below), this will avoid having the programmer do it in a cpp file.
namespace Utility
{
class String
{
// Class Implementation
};
}
using Utility::String;
My understanding is that if the user includes the header String.h and String is in Utility then the programmer will want to use String. Obviously this could be bad if there are outside classes chain including a bunch of files which dirty up the namespace so I thought how about making it a #define instead.
namespace Utility
{
class String
{
// Class Implementation
};
}
#ifdef AUTO_DECLARE_NAMESPACE
using Utility::String;
#endif
That way, programmers that want this extended functionality can get it.
Would this a good idea or is there something I'm overlooking?
There is no point in using namespaces if you are just going to add a using declaration for each and every name declared in the namespace.
Let users of your header files decide how they want to use the headers. If someone wants to use a using declaration, let him do it in the .cpp file directly; this will make the code in that .cpp file clearer since it will be apparent where the name originated.
This seems at best pointless, and at worst annoying.
What is wrong with having developers decide which namespaces to use and what to qualify fully?
Honestly, I believe that's what the using namespace directive is for. There's no need for you to add this preprocessor mechanism, considering the using namespace directive does just that.
Couldn't you have another .h file with all your usings like my_lib_import_names.h and just #include that to get what you want?
You would probably have problem with classes not being declared but you could probably bypass it by using something like:
#ifdef UTILITY_STRING_H_
using Utility::String;
#endif
..
#ifdef UTILITY_SOMETHING_ELSE_H
using Utility::SomethingElse;
#endif
..
What do you think?
That way you could retain the "expected" behavior in your library .h but also have your the way you like. You also get to keep the benefit of the namespace over your classes (at the expense of having to maintain your new .h file).