C++ Class Header Files Organization

C++ class header files organization

Some general guidelines:

  • Pair up your interfaces with implementations. If you have foo.cxx, everything defined in there had better be declared in foo.h.
  • Ensure that every header file #includes all other necessary headers or forward-declarations necessary for independent compilation.
  • Resist the temptation to create an "everything" header. They're always trouble down the road.
  • Put a set of related (and interdependent) functionality into a single file. Java and other environments encourage one-class-per-file. With C++, you often want one set of classes per file. It depends on the structure of your code.
  • Prefer forward declaration over #includes whenever possible. This allows you to break the cyclic header dependencies. Essentially, for cyclical dependencies across separate files, you want a file-dependency graph that looks something like this:

    • A.cxx requires A.h and B.h
    • B.cxx requires A.h and B.h
    • A.h requires B.h
    • B.h is independent (and forward-declares classes defined in A.h)

If your code is intended to be a library consumed by other developers, there are some additional steps that are important to take:

  • If necessary, use the concept of "private headers". That is, header files that are required by several source files, but never required by the public interface. This could be a file with common inline functions, macros, or internal constants.
  • Separate your public interface from your private implementation at the filesystem level. I tend to use include/ and src/ subdirectories in my C or C++ projects, where include/ has all of my public headers, and src/ has all of my sources. and private headers.

I'd recommend finding a copy of John Lakos' book Large-Scale C++ Software Design. It's a pretty hefty book, but if you just skim through some of his discussions on physical architecture, you'll learn a lot.

How to organize header/code files in C++ if I want only well-architectured workspace but not necessarily separated compilation?

As Hristo said, you should generally write the definitions in header files and write the implementation in the source code files.

To answer your question however:

But the problem is that I have many constants, includes and some other things that I want to have all in one place.

What I've typically done is create a single file called something like "common.h" or "defs.h" (I took the idea from Doom...) and that file has many defines that you find you need throughout your entire program. If you are using constants, declare the constants in the header file like so:

    extern const int MAX_SOMETHING;
extern const bool TRUTH_VALUE;

and make a complementary source file (defs.cpp or common.cpp) that defines these constants:

    const int MAX_SOMETHING = 5;
const bool TRUTH_VALUE = true;

so now when you include the common/defs.h in other source files, the extern keyword will tell that source file that the definition is in another source file (its in the common/defs.cpp) so it will find the definition in there, and you can use it anywhere where you have included common/defs.cpp.

How to organize your code entities in header files?

The first thing to remember is that a header is for use by other files; it should contain only the information needed by consumers of some service to use that service. A program in a single source file doesn't need a header (for the functions it defines; it will for the 'system' functions it uses, though). The header is used to ensure consistency between the provider of the service and the consumers of the service.

[Do you] put every class declaration in a header file?

No. Many classes, but certainly not every class.

If a class is only used by code in the source file, nothing outside the file needs to know about the class at all. The class should be specified in the source file, not in a header.

Even if a class is used in the interface, consider carefully whether the detailed declaration is needed, or whether it is sufficient to provide a forward declaration of the class.

How about global entities?

You should not have many 'global entities' other than functions. Avoid global variables as much as possible. If the global entity is going to be needed by other files, then it should be declared in an appropriate header, usually but not always the one that defines the class to which it belongs. If a 'global entity' is needed only in a single file, it should be defined in an appropriate namespace (often the anonymous namespace).

Do I need to put every declaration in a different file?

No. You group them together. Consider the Standard C++ Library. Many of the headers define more than one declaration. But each header defines a set of related declarations. You want to strike a balance between separating everything into different headers and having so many headers you can't find anything.

A first rule of thumb would be 'one header per source file that defines services'. It has to be used judiciously, though.

If several source files are needed to implement the complete set of services, then a single header may provide the external definitions for the complete set of services (and there will likely be a second, private header used only by the source files that implement the service, defining the details that they need to share between themselves, without sharing with consumers).

At the other extreme, sometimes a source file will implement several sets of services. It would be unusual if those services are not closely related — bad engineering. If they are related, then a single header can suffice. I suppose one could have two public headers for a single source file, but the situation would be extremely unusual.

Separating class code into a header and cpp file

The class declaration goes into the header file. It is important that you add the #ifndef include guards. Most compilers now also support #pragma once. Also I have omitted the private, by default C++ class members are private.

// A2DD.h
#ifndef A2DD_H
#define A2DD_H

class A2DD
{
int gx;
int gy;

public:
A2DD(int x,int y);
int getSum();

};

#endif

and the implementation goes in the CPP file:

// A2DD.cpp
#include "A2DD.h"

A2DD::A2DD(int x,int y)
{
gx = x;
gy = y;
}

int A2DD::getSum()
{
return gx + gy;
}


How do I create two classes that refer to each other in different header files?

Since you've forward declared the class Organization in Seller.h there is no need to write #include "Organisation.h". Similarly, in Organization.h" since you've forward declared class Seller there is no need to write #include "Seller.h". Also, always take into account cyclic dependency like in your program Organization.h has a #include "Seller.h" and then Seller.h has a #include "Organization.h"

The running(successfully compiled) program can be seen here.

Organization.h

#ifndef ORGANIZATION_OOP3_H
#define ORGANIZATION_OOP3_H
//#include "Seller.h"
#include <vector>
class Seller;
class Organization{
std::vector<Seller*> own;

};
#endif

Seller.h

#ifndef OOP_3_SELLER_H
#define OOP_3_SELLER_H
//#include "Organization.h"
class Organization;
class Seller{
protected:
Organization*owner;

};
#endif

In the .cpp files(also called source files) you should include the headers using #include.

Your program has other problems too like many(and i mean many many)of the methods in Seller.h have no return value for methods that have non-void return type.

I tried solving some of the problems in you github code but there are just too many problems(errors and warnings) to solve. Also i would suggest you to use cpp files as well.

How to design a big class header file in c++?

Instead of making the inner classes inner classes, you're better off leaving them on their own, eventually in their own namespace:

// in file foo/bar.h
namespace foo_detail
{
class Bar
{
};
};

// in file foo.h
#include "foo/bar.h"

class Foo
{
private:
foo_detail::Bar theBar;
};

This way your Foo class definition is not overly complicated, your definition files are small (and easy to skim over), you do not include things in your Foo class definition (respecting the principle of least surprise - or decreasing the number of WTF/LOC as they say) and when you look at the definition for Bar, you can clearly see it's an implementation details for foo (by the namespace name if nothing else).

Namespaces are good. Trust the namespaces.



Related Topics



Leave a reply



Submit