Constants and Classes Declarations Across Multiple Source Files in C++ - c++

I am sure this problem is asked a lot but I can't seem to find anything relevant. I have multiple source files in a C++ project. In typical fashion, there are multiple header files with class and function declarations and associated source files with their definitions. The problem is that when I try to use one of my classes defined in another file as a member for a class in a different file, I get compile errors even when uses the #include directive. What fixes the problem is by prototyping (is that the right word?) the class first before declaring it a member. So if ClassA is in one file and ClassB is in another and I want to use a ClassA member in ClassB I must write:
// ClassA.h
class ClassA {
public: ClassA (void); };
// ClassB.h
class ClassA; // prototype
class ClassB {
public: ClassA* ca; };
Is this normal? It doesn't matter if I use pointers or instances, I still must prototype them. I have found that I also must prototype structs and enums if they are in separate files. I can't seem to use constants declared using #define, or const across multiple files I get errors that they are undefined so I am not sure how to give them more than file scope. The same goes for typedefs. I am sure there is some easy fix to this that I am not remembering... any help is appreciated!

The word you’re looking for is “declare”, not “prototype”.
In any case, that’s normal. Usually you’d just include the relevant header files:
// ClassB.h
#include "ClassA.h"
class ClassB {
public: ClassA* ca; };
This will cause problems with circular references, though (but in all other cases it’s fine).
Another thing: Don’t forget your include guards, to protect against multiple inclusion of a file. That is, always write header files in the following way:
#ifndef UNIQUE_IDENTIFIER_HERE
#define UNIQUE_IDENTIFIER_HERE
// Rest of header file here.
#endif // ndef UNIQUE_IDENTIFIER_HERE
The UNIQUE_IDENTIFIER_HERE is usually an all-uppercase variant of the header file name, e.g. ‹PROJECTNAME›_‹PATH_TO_HEADER›_‹HEADERNAME›_H. For example, I’m currently working in a project (called “SeqAn”) that has a header file in the path parallel/taskdata.h. The unique identifier I use is thus SEQAN_PARALLEL_TASKDATA_H.

Yes it is obvious way.
This approach is most suitable when you're trying to avoid mutual dependencies among headers. If you're sure that no mutual dependency appears between two headers it is normal that you #include one in another.

To expand on Konrad's answer:
Yes, that's fine and dandy when you don't have to deal with circular references. If you do have to worry about circular inheritance, the diamond problem, or anything of the sort, here's a solution I found in someone else's question:
// ClassA.h
class ClassB;
class ClassA {
public:
ClassB* cb;
};
// ClassA.cpp
#include "ClassA.h"
#include "ClassB.h"
// code
// ClassB.h
#include "ClassA.h"
class ClassB {
public:
ClassA* ca;
};
// ClassB.cpp
#include "ClassB.h"
// code
As long as ClassA only tries to access members of ClassB inside member functions, and the member functions are all in the source file, you can just use a class declaration in the header, and leave the #include for the source file, where ClassA.h's include guard will solve the problem for you.

Related

How to include twice a header that has static variable definitions?

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.

Are Forward Declarations Needed If You Already Have Include Guards?

If you have a set of header files with include guards, is it really necessary to have forward declarations?
I've been doing this out of habit in my code, and I recommended a colleague add forward declarations to their code, but when they asked whether it was really necessary because of the include guards already present, I was at a bit of a loss. It seems like it's good practice, but wouldn't include guards solve all of the problems that forward declarations do?
Here's an example. Suppose I have a header file like so:
//This is the header file of class B
class MyClassA; //This is forward declaration
class B{
private:
MyClassA *myClass; //pointer to MyClassA
public:
B(){}
~B(){};
void print(MyClassA* myClass); //Passing by reference. Not calling any methods of MyClassA.
}
If I know that there is an include guard in MyClassA.h, would the above be better practice than the following? And, if so, why?
#include “MyClassA.h”
class B{
private:
MyClassA *myClass; //pointer to MyClassA
public:
B(){}
~B(){};
void print(MyClassA* myClass); //Passing by reference. Not calling any methods of MyClassA.
}
Would the second example also prevent a circular declaration/multiple declaration?
You are mixing two unrelated concepts.
You use forward declaration when you need something by name only.
You use include guards to prevent processing of the same code multiple times in a single translation unit, i.e. .cpp file. Whether you use include guards or not is based on the intended use of the .h file. Most of the time, you don't want the contents of the file to be processed multiple times in a .cpp file but there are use cases where allowing that is essential. For the later category of uses, you must not use include guards.
You can combine them anyway you want.
It's ok to:
Use forward declarations AND use include guards.
Use forward declarations AND not use include guards.
Not use forward declarations AND use include guards.
Not use forward declarations AND not use include guards.

OOP C++ - Error as A.h includes B.h which includes A.h again

I'm learning OOP and have a doubt. Suppose I have a file ClassA.h that includes ClassB.h, and at some point my ClassB.h needs to include ClassA.h.
This yelds an error and I think I understand why that happens since I get an infinite include loop. But what to do in this case? Is there a way around this error? Or should I rethink my classes to avoid it? Does this mean my class organization is poorly designed? If so, what would be a way to arrange my "class diagram" and avoid this?
I just want to know what would be the best practice in this scenario. Also, why doesn't the "#pragma once" directive solve this problem? Thanks in advance.
You may also get around this by using forward declaration. Provided you do not create actual object of the class you are including in the header or not inheriting from it, say if you only need pointers of them in the headers you can do this.
Example:
ClassA.h
class ClassB;
//rest of the codes here
ClassB.h
class ClassA;
//rest of the codes here
ClassA.cpp
#include ClassA.h
#include ClassB.h
ClassB.cpp
#include ClassB.h
#inlcude ClassA.h
There is a way to fix it, but it also means your class organization is broken.
The way to fix it is called an 'include guard', though many compilers also support the #pragma once directive. I suppose it isn't working because #pragma once probably doesn't consider a header file included until the entire thing is parsed. And since the recursive inclusion happens in the middle of the header file, it isn't finished being parsed yet.
An include guard is something like this:
In ClassA.h:
#pragma once // Just because. It really should help.
#ifndef INCLUDED_CLASSA_H
#define INCLUDED_CLASSA_H
#include "ClassB.h"
//... rest of header file
#endif
In ClassB.h:
#pragma once // Just because. It really should help.
#ifndef INCLUDED_CLASSB_H
#define INCLUDED_CLASSB_H
#include "ClassA.h"
//... rest of header file
#endif
The organization problem is called a circular dependency, and circular dependencies are generally a bad idea. There are a number of different ways of breaking them, but which to use depends on the exact nature of and original reason for the dependency.
Depending on the problem you can use one of a variety of techniques:
Inheritance from a common base class
Turning one of the two classes into a base class for the other - This is a variant of the previous one.
Forward declarations - This is not so desired because it doesn't really break the circular dependency, it just arranges it so you don't need to also have a problematic circular include dependency.
Turning some part of both classes into a class that they both can use - This is another variant of common base class that uses composition instead of inheritance.
There are other techniques. There is, in fact, a book that has a really wide variety of techniques to use in various situations because removing circular dependencies is a big theme of the book. That book is "Large-Scale C++ Software Design" by John Lakos.
In my past experience , I have solved same problem by using Inheritance.
The way I have solved is .
ClassA -> ClassB : ClassB was inherited by ClassA.
ClassA had common needs that ClassB and ClassA wanted.
then I had resolved "Recursive Include Problem"

Class Definition Instance Instantiation Question

I have a class imgmanager that allows me to load all my images exactly once, it's quite nice, and while prototyping I had all of my files in one place, so I didn't have to worry about cyclical definitions. However after separating all of my classes I have a problem.
My Header File
#ifndef IMAGEMANAGER_H
#define IMAGEMANAGER_H
#include "Img.h"
#include <vector>
#include <map>
#include <string>
class imgmanager{
protected:
std::vector<sf::Image*> images;
std::map<std::string,int> positions;
public:
sf::Image* addimg(std::string path); //relative to resources
sf::Image* getimg(std::string path);
int size();
virtual ~imgmanager();
sf::Image* operator[](int);
}imagemgr;
#endif
With the instance created after the } and before the ; my compiler complains at me:
So I ask: What should I do to have a global instance of my imagemgr class? Should I just make a global header file and create an instance? (in this particular case I can just make a global variable in my main.cpp, none of the headers require the instance)
Don't create object instances in headers.
Create your object instance in one source file.
If you need to access it across multiple Translation Units, put this in your header:
extern imgmanager imagemgr; // declaration
This will inform all code that can "see" the header that there exists a so-named object; but it will still only actually be defined in the one source file where you wrote:
imgmanager imagemgr; // definition
(This is analogous to the way in which you declare functions in a header, but define them in precisely one source file:
void f(); // declaration
void f() { ... } // definition
)
The above general advice dutifully imparted, I would now question the rationale of having a class at all if you're only going to use one, single, global instance of it. Either make it a "singleton" class, or use free functions in a namespace instead.
If you require a single global instance, i suggest you make the ImageManager a "Singleton".
I'm unsure what to do for complex types, but for a global declaration of a simple data-type you should declare the variable "extern" in the header, and instantiate it in exactly one module (.cpp file).

What kind of bad things would happen if you write the whole class in a single file in C++?

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.