what is the best way to handle circular inclusions in the situation where I have a class that communicates with another class, like an API and gets callbacks from that class.
Assume I have a class
.h
class Requestor;
class Api
{
public:
Api();
void Request();
int DoStuff();
private:
Requestor *p_rq_;
};
.cpp
#include "api.h"
#include "requestor.h"
Api::Api()
{
}
void Api::Request() {
this->DoStuff();
}
void Api::ReturnRequestId( int id ) {
this->p_rq->SetLastRequestId( id );
}
and
.h
class Api;
class Requestor
{
public:
Requestor();
void MakeRequest();
void SetLastRequestId( int );
private:
Api api_;
int last_request_id_;
};
.cpp
#include "requestor.h"
#include "api.h"
Requestor::Requestor()
{
}
void Requestor::MakeRequest() {
this->api_.Request();
}
void Requestor::SetLastRequestId( int id ) {
this->last_request_id_ = id;
}
In case requestor sends a request and at some point the api gets an id and wants to pass that back to the requestor, how can I do that without including each others .h file which would lead to circular inclusion?
Assume that I cant simply have the function MakeRequest return the id as I dont want to hold that thread until api gets the id?
I am fairly new to c++ and programming, so I may miss the obvious solution. Since I need to call member functions of each other, it is my understanding that forward declaration does not work here.
Also, Api and Requestor should be separate libraries, so I can't make them one class.
You have two different issues, circular dependency between your classes and multiple inclusion of the same header file.
Multiple inclusion is not caused only by simple circular dependencies, like in your case. The usual way to make sure a header is included once and only once in a source file is to use include guards. Normally a header file looks like this:
#ifndef SOME_UNIQUE_NAME_
#define SOME_UNIQUE_NAME_
... header contents ...
#endif
This ensures that no matter how many times a header gets included in a source file (either directly or indirectly), only the first time its contents are actually included, subsequent inclusions are skipped by the preprocessor due to that macro. The macro name must be unique (for obvious reasons), and it is usually some kind of prefix followed by the header name, e.g. LIBNAME_MODULENAME_REQUESTOR_H_.
A widely used alternative, supported by most modern compilers even if not standard as far as I know, is to use a pragma directive at the beginning of the header:
#pragma once
... header contents
Your other issue is circular dependency between your classes. Here you've already found one way to go around it: your Api class holds a pointer to a Requestor object and not the object itself. This allows you to use a forward declaration in Api.h and not include the full class definition.
The Requestor class however holds an Api object, not just a pointer, so the full Api class definition must be available at the point where the api_ member is declared. So you can't use a forward declaration for the Api class in this case, you must actually include the full definition.
Use
#ifndef __filex__
#define __filex__
At the beginning of each .h and
#endif
At the end.
This way, the .h file is read only once
Related
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.
When I started learning C++ I learned that header files should typically be #included in other header files. Just now I had someone tell me that I should include a specific header file in my .cpp file to avoid header include creep.
Could someone tell me what exactly that is, why it is a problem and maybe point me to some documentation on when I would want to include a file in another header and when I should include one in a .cpp file?
The "creep" refers to the inclusion of one header including many others. This has some unwanted consequences:
a tendency towards every source file indirectly including every header, so that a change to any header requires everything to be recompiled;
more likelihood of circular dependencies causing heartache.
You can often avoid including one header from another by just declaring the classes you need, rather than including the header that gives the complete definition. Such an incomplete type can be used in various ways:
// Don't need this
//#include "thingy.h"
// just this
class thingy;
class whatsit {
// You can declare pointers and references
thingy * p;
thingy & r;
// You can declare static member variables (and external globals)
// They will need the header in the source file that defines them
static thingy s;
// You can declare (but not define) functions with incomplete
// parameter or return types
thingy f(thingy);
};
Some things do require the complete definition:
// Do need this
#include "thingy.h"
// Needed for inheritance
class whatsit : thingy {
// Needed for non-static member variables
thingy t;
// Needed to do many things like copying, accessing members, etc
thingy f() {return t;}
};
Could someone tell me what exactly [include creep] is
It's not a programming term, but interpreting it in an Engish-language context would imply that it's the introduction of #include statements that are not necessary.
why it is a problem
Because compiling code takes time. So compiling code that's not necessary takes unnecessary time.
and maybe point me to some documentation on when I would want to include a file in another header and when I should include one in a .cpp file?
If your header requires the definition of a type, you will need to include the header that defines that type.
#include "type.h"
struct TypeHolder
{
Type t;
// ^^^^ this value type requires the definition to know its size.
}
If your header only requires the declaration of a type, the definition is unnecessary, and so is the include.
class Type;
struct TypeHolder
{
Type * t;
// ^^^^^^ this pointer type has the already-known size of a pointer,
// so the definition is not required.
}
As an anecdote that supports the value of this practice, I was once put on a project whose codebase required ONE HOUR to fully compile. And changing a header often incurred most or all of that hour for the next compilation.
Adding forward-declarations to the headers where applicable instead of includes immediately reduced full compilation time to 16 minutes, and changing a header often didn't require a full rebuild.
Well they were probably referring to a couple of things ("include creep" is not a term I've ever heard before). If you, as an extreme rule, only include headers from headers (aside from one matching header per source file):
Compilation time increases as many headers must be compiled for all source files.
Unnecessary dependencies increase, e.g. with a dependency based build system, modifying one header may cause unnecessary recompilation of many other files, increasing compile time.
Increased possibility of namespace pollution.
Circular dependencies become an issue (two headers that need to include each other).
Other more advanced dependency-related topics (for example, this defeats the purpose of opaque pointers, which causes many design issues in certain types of applications).
As a general rule of thumb, include the bare minimum number of things from a header required to compile only the code in that header (that is, enough to allow the header to compile if it is included by itself, but no more than that). This will combat all of the above issues.
For example, if you have a source file for a class that uses std::list in the code, but the class itself has no members or function parameters that use std::list, there's no reason to #include <list> from the class's header, as nothing in the class's header uses std::list. Do it from the source file, where you actually need it, instead of in the header, where everything that uses the class also has to compile <list> unnecessarily.
Another common technique is forward declaring pointer types. This is the only real way to combat circular dependency issues, and has some of the compilation time benefits listed above as well. For example, if two classes refer to each other but only via pointers:
// A.h
class B; // forward declaration instead of #include "B.h"
class A {
B *b;
}
// B.h
class A; // forward declaration instead of #include "A.h"
class B {
A *a;
}
Then include the headers for each in the source files, where the definitions are actually needed.
Your header files should include all headers they need to compile when included alone (or first) in a source file. You may in many cases allow the header to compile by using forward declarations, but you should never rely on someone including a specific header before they include yours.
theres compie time to think of, but there's also dependancies. if A.h includes B.h and viceversa, code won't compile. You can get around this by forward referancing your class, then including the header in the cpp
A.h
class B;
class A
{
public:
void CreateNewB():
private:
B* m_b;
};
A.cpp
#include "B.h"
A::CreateNewB()
{
m_b = new B;
}
This surely is a noob question, but I can't find an answer in Doxygen documentation. I'm not sure whether using:
#file
or
#class
when documenting my header files.
The reason is that if I put file, then all the comments appear in the Files tab only, but not in the Classes tab (per each).
For cpp it's ok, I just use file and it's good, but if I use both file and class in the header (file at the beginning and class right before the start of the class declaration) then I get duplicated entries for the class in the generated documentation...
What I'm doing wrong? Any suggestions? Ideas?
Regards,
Alex
Edit: I run into a new problem now. In order to avoid circular dependecies I declare my class twice in a header file (probably this is not the best way to avoid circular dependencies but it normally works for me), for instance:
#ifndef EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DECL
#define EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DECL
namespace eu_sofia_kpi_common
{
class KPI_CPP_API AbstractThread;
}
#define EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DECL_END
#endif EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DECL
#ifdef EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DECL_END
#ifndef EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DEF
#define EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DEF
namespace eu_sofia_kpi_common
{
class KPI_CPP_API AbstractThread
{
public:
AbstractThread();
virtual ~AbstractThread();
///start method, derived classes must implement this method to initialize their boost::shared_ptr<boost::thread> pointer member object
virtual int start() = 0;
//stop method
virtual void stop() = 0;
protected:
///Pointer to a boost thread to be inherited and that children classes must use in the implementation of the start and stop methods
boost::shared_ptr<boost::thread> m_thread;
};
}
#endif EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DEF
#endif EU_SOFIA_KPI_COMMON_ABSTRACTTHREAD_DECL_END
As you can see, I have a forward declaration prior my "real" declaration. Now if I use #class, Doxygen complains about inconsystency issues related with this class, although it generates the documentation for the class. My guess is that anything that is surrounded by #ifdef or #ifndef Doxygen does not seem to like it very much...
I usually use neither, unless I want to specify an alternate include path or something like that. Normally it looks like this:
/// Tunables loader.
/** This class contains a set of functions for loading tunables from
* file. Usually you only need one QuaTunablesLoader object in your
* program. Once its work is done, you can safely destroy it.
*
* ... blah, blah, blah ...
* */
class QuaTunablesLoader {
This is actually equivalent to using #class, so the answer to your question is yes, you should use #class when documenting classes. If your header file doesn't contain anything else, you probably shouldn't document it at all, as the documentation would only say something like "this file contains the declaration of the class SomeClass" anyway. If the file contains something more, like friend functions, you should document the file too (obviously, using #file), possibly providing a reference to the class.
In C# or Java, classes are declared and defined at the same time. In C++, the norm is to do that separately. What if we write the whole class in one , say .cpp, file and include that in files that references to it, what kinds of bad thing technically would happen besides a lengthened compilation process?
If your implementation of MyClass is all in the header file MyClass.h then any file you needed to implement MyClass will be included whenever someone includes MyClass.h.
If you change any part of MyClass.h, even if it's trivial (such as adding a comment or even a space) then all files that include it will have to recompile, even if the interface hasn't changed.
Neither of these matters for toy projects, but as you noted, when you have a program that consists of hundreds (or thousands, etc.) of class files, the added compilation time alone makes it worthwhile to separate out implementation from interface.
For instance, if I have the following:
// MyClass.h
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include "Inventory.h"
class MyClass
{
public:
MyClass();
void processInventory(Inventory& inventory)
{
// Do something with each item in the inventory here
// that uses iostream, iomanip, sstream, and string
}
private:
// ...
};
It would more ideomatically be written as:
// MyClass.h
class Inventory;
class MyClass
{
public:
MyClass();
void processInventory(Inventory& inventory);
private:
// ...
};
// MyClass.cc
#include "MyClass.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include "Inventory.h"
MyClass()::MyClass()
{
}
void MyClass()::processInventory(Inventory& inventory)
{
// Do something with each item in the inventory here
// that uses iostream, iomanip, sstream, and string
}
Notice: Including MyClass.h doesn't mean iostream, iomanip, sstream, string, or Inventory.h have to be parsed. Changing how processInventory works doesn't mean all files using MyClass.h have to be recompiled.
Notice how much easier it can be to figure out how to use MyClass now. Header files serve an important purpose: they show people how to use your class. With the modified MyClass.h it's easy to see the list of functions. If each function is defined in the header, then you can't look at just the list of functions. That makes it harder to figure out how to use the class.
You may break the one definition rule.
If you write this:
class foo
{
public:
void doit();
};
foo::doit() {}
and include that in multiple classes, you will have multiple definitions of foo::doit and your link will fail.
But if you make all your classes inline, either by defining them within the class declaration:
class foo
{
public:
void doit() {
}
};
or by explicitly making them inline:
class foo
{
public:
void doit();
};
inline void foo::doit() {}
then you can include that file as many times as you like.
The linker will see multiple definitions of the class's members when you try to combine multiple such objects. Thus, you won't be able to produce a binary from source files that include anything in more than one place.
Typically you separate the declaration and definition of a class. This allows you to use your class in different source files by simply including the declaration.
If you include a .cpp which has both declaration and definition into 2 different source files then that class will be doubly defined.
Each .cpp that the class is included into will compile fine into object files. However each class must have only 1 definition total or else you will not be able to link your object files together.
The most important thing to understand about #include contrasted with other languages importing methods, is that #include COPIES the contents of that file where the #include directive is placed. So declaring and defining a class in the same file will create three things:
Significantly increase your compile
times.
If your definitions are not inline
you will get linker errors, since
the compiler finds multiple
definitions to the same functions
That would expose the implementation
to the user, instead of only the interface.
That is why it is common practice to define large classes in separate files, and on some ocassions, really small classes with small implementations (like smart pointers) in one file(To also implicitly inline methods).
#Bill
I think it is important to underscore Bill's point:
Notice how much easier it can be to
figure out how to use MyClass now.
Header files serve an important
purpose: they show people how to use
your class.
the .h file being more or less the "public" doc to allow the understanding of how your class works in some ways conceptually--an Interface. Remember the source file should be thought of as proprietary. I remember learning a lot about how Unix worked in my early C/C++ days by reading header files. Also remember that inline function complexities should be no more than accessor's
A big reason for a class to be defined in a cpp-file is that it isn't needed publically, it is just a helper function (like e.g. a functor). Some people seem to be afraid to put the complete class in the cpp-file, while that just shows your intent of only using the class there.
Files are usually the atoms of your version control system - if you partition things sensibly into different files, then it becomes possible for a team of developers to check out only the parts they each need to work on. Put everything in one file and you can't do that.
Instead of doing
#include "MyClass.cpp"
I would like to do
#include "MyClass.h"
I've read online that not doing so is considered bad practice.
Separate compilation in a nutshell
First, let's get some quick examples out there:
struct ClassDeclaration; // 'class' / 'struct' mean almost the same thing here
struct ClassDefinition {}; // the only difference is default accessibility
// of bases and members
void function_declaration();
void function_definition() {}
extern int global_object_declaration;
int global_object_definition;
template<class T> // cannot replace this 'class' with 'struct'
struct ClassTemplateDeclaration;
template<class T>
struct ClassTemplateDefinition {};
template<class T>
void function_template_declaration();
template<class T>
void function_template_definition() {}
Translation Unit
A translation unit (TU) is a single source file (should be a **.cpp* file) and all the files it includes, and they include, etc. In other words: the result of preprocessing a single file.
Headers
Include guards are a hack to work around lack of a real module system, making headers into a kind of limited module; to this end, including the same header more than once must not have an adverse affect.
Include guards work by making subsequent #includes no-ops, with the definitions available from the first include. Because of their limited nature, macros which control header options should be consistent throughout a project (oddball headers like <assert.h> cause problems) and all #includes of public headers should be outside of any namespace, class, etc., usually at the top of any file.
See my include guard naming advice, including a short program to generate include guards.
Declarations
Classes, functions, objects, and templates may be declared almost anywhere, may be declared any number of times, and must be declared before referring to them in any way. In a few weird cases, you can declare classes as you use them; won't cover that here.
Definitions
Classes may be defined at most once[1] per TU; this typically happens when you include a header for a particular class. Functions and objects must be defined once in exactly one TU; this typically happens when you implement them in a **.cpp* file. However, inline functions, including implicitly inline functions inside class definitions, may be defined in multiple TUs, but the definitions must be identical.
For practical purposes[2], templates (both class templates and function templates) are defined only in headers, and if you want to use a separate file, then use another header[3].
[1] Because of the at-most-once restriction, headers use include guards to prevent multiple inclusion and thus multiple definition errors.
[2] I won't cover the other possibilities here.
[3] Name it blahblah_detail.hpp, blahblah_private.hpp, or similar if you want to document that it's non-public.
Guidelines
So, while I'm sure everything above is all a big ball of mud so far, it's less than a page on what should take up a few chapters, so use it as a brief reference. Understanding the concepts above, however, is important. Using those, here's a short list of guidelines (but not absolute rules):
Always name headers consistently in a single project, such as **.h* for C and **.hpp* for C++.
Never include a file which is not a header.
Always name implementation files (which are going to be directly compiled) consistently, such as **.c* and **.cpp*.
Use a build system which can compile your source files automatically. make is the canonical example, but there are many alternatives. Keep it simple in simple cases. For example, make can be used its built-in rules and even without a makefile.
Use a build system which can generate header dependencies. Some compilers can generate this with command-line switches, such as -M, so you can make a surprisingly useful system easily.
Build Process
(Here's the tiny bit that answers your question, but you need most of the above in order to get here.)
When you build, the build system will then go through several steps, of which the important ones for this discussion are:
compile each implementation file as a TU, producing an object file (**.o*, **.obj*)
each is compiled independently of the others, which is why each TU needs declarations and definitions
link those files, along with libraries specified, into a single executable
I recommend you learn the rudiments of make, as it is popular, well-understood, and easy to get started with. However, it's an old system with several problems, and you'll want to switch to something else at some point.
Choosing a build system is almost a religious experience, like choosing an editor, except you'll have to work with more people (everyone working on the same project) and will likely be much more constrained by precedent and convention. You can use an IDE which handles the same details for you, but this has no real benefit from using a comprehensive build system instead, and you really should still know what it's doing under the hood.
File Templates
example.hpp
#ifndef EXAMPLE_INCLUDE_GUARD_60497EBE580B4F5292059C8705848F75
#define EXAMPLE_INCLUDE_GUARD_60497EBE580B4F5292059C8705848F75
// all project-specific macros for this project are prefixed "EXAMPLE_"
#include <ostream> // required headers/"modules"/libraries from the
#include <string> // stdlib, this project, and elsewhere
#include <vector>
namespace example { // main namespace for this project
template<class T>
struct TemplateExample { // for practical purposes, just put entire
void f() {} // definition of class and all methods in header
T data;
};
struct FooBar {
FooBar(); // declared
int size() const { return v.size(); } // defined (& implicitly inline)
private:
std::vector<TemplateExample<int> > v;
};
int main(std::vector<std::string> args); // declared
} // example::
#endif
example.cpp
#include "example.hpp" // include the headers "specific to" this implementation
// file first, helps make sure the header includes anything it needs (is
// independent)
#include <algorithm> // anything additional not included by the header
#include <iostream>
namespace example {
FooBar::FooBar() : v(42) {} // define ctor
int main(std::vector<std::string> args) { // define function
using namespace std; // use inside function scope, if desired, is always okay
// but using outside function scope can be problematic
cout << "doing real work now...\n"; // no std:: needed here
return 42;
}
} // example::
main.cpp
#include <iostream>
#include "example.hpp"
int main(int argc, char const** argv) try {
// do any global initialization before real main
return example::main(std::vector<std::string>(argv, argv + argc));
}
catch (std::exception& e) {
std::cerr << "[uncaught exception: " << e.what() << "]\n";
return 1; // or EXIT_FAILURE, etc.
}
catch (...) {
std::cerr << "[unknown uncaught exception]\n";
return 1; // or EXIT_FAILURE, etc.
}
This is called separate compilation model. You include class declarations into each module where they are needed, but define them only once.
In addition to hiding implementation details in cpp files (check other replies), you can additionally hide structure details by class forward declaration.
class FooPrivate;
class Foo
{
public:
// public stuff goes here
private:
FooPrivate *foo_private;
};
The expression class FooPrivate says that FooPrivate is completely defined somewhere else (preferably in the same file where Foo's implementation resides, before Foo's stuff comes. This way you make sure that implementation details of Foo(Private) aren't exposed via the header file.
You needn't include .c or .cpp files - the compiler will compile them regardless whether they're #included in other files or not. However, the code in the .c/.cpp files is useless if the other files are unaware of the classes/methods/functions/global vars/whatever that's contained in them. And that's where headers come into play. In the headers, you only put declarations, such as this one:
//myfile.hpp
class MyClass {
public:
MyClass (void);
void myMethod (void);
static int myStaticVar;
private:
int myPrivateVar;
};
Now, all .c/.cpp files that will #include "myfile.hpp" will be able to create instances of MyClass, operate on myStaticVar and call MyClass::myMethod(), even though there's no actual implementation here! See?
The implementation (the actual code) goes into myfile.cpp, where you tell the compiler what all your stuff does:
//myfile.cpp
int MyClass::myStaticVar = 0;
MyClass::MyClass (void) {
myPrivateVar = 0;
}
void MyClass::myMethod (void) {
myPrivateVar++;
}
You never include this file anywhere, it's absolutely not necessary.
A tip: create a main.hpp (or main.h, if you prefer - makes no difference) file and put all the #includes there. Each .c/.cpp file will then only need to have have this line: #include "main.hpp". This is enough to have access to all classes, methods etc. you declared in your entire project :).
You should not include a source file (.c or .cpp). Instead you should include the corresponding header file(.h) containing the declarations. The source files needs to be compiled separately and linked together to get the final executable.
Cpp files should be defined in your compiler script to be compiled as object files.
What ide are you using?
I am going to assume you are compiling with gcc, so here is the command to compile two .cpp files into one executable
gcc -o myclasses.out myclass.cpp myotherclass.cpp
You should only use #include to include class definitions, not the implentation
One thing you will want to watch out for when including you class declarations from a .h/.hpp is make sure it only ever gets included once. If you don't do this you will get some possibly cryptic compiler errors that will drive you up the wall.
To do this you need to tell the compiler, using a #define, to include the file only if the #define does not already exist.
For example (MyClass.h):
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass
{
// Memebers and methods
}
#endif
// End of file
This will guarantee your class declaration only gets included once even if you have it included in many different .cpp files.