I have always thought of header files as a sort of 'public interface' describing a class, in which case it would be better to keep private fields and functions in the .cpp file.
I understand that private fields need to be in the header so that other classes can tell how much memory an instance of a class will consume, but it occurred to me as I was about to write a private helper function, that this function could be made static, in which case there was no need for it to be 'part of the class' at all, it could just as easily be a regular function in the class definition's .cpp file.
It then occurred to me that all private functions could potentially be rewritten to be static by accepting pointers/references to class fields instead of expecting to be defined in the class.
This would eliminate the need to declare any private functions in the header file.
I do like to follow conventions, so is it considered an established convention in C++, that non-static private functions should be in the header file? What about static functions or static constants?
I'm going to put in some code to explain what I'm getting at:
.h file:
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass
{
private:
int x;
public:
void combineWithX(int y);
};
#endif
.cpp file
#include "SomeClass.h"
void someHelper(int* x)
{
*x = (*x) + 1;
}
void SomeClass::combineWithX(int y)
{
someHelper(&x);
x += y;
}
Note that someHelper(int* x) in the .cpp file references the private member x in spirit, but not directly, and therefore does not need to appear in the header. I'm wondering if this sort of thing is considered 'bad style'.
Private helper functions can be hidden from the public header file by moving them to an inner class. This works because the inner class is considered part of the class and can access the surrounding class's private members.
Unlike the PIMPL idiom, this does not have any dynamic allocation or indirection penalty. Compile times should be faster when editing/refactoring private functions, as there isn't any need to recompile all the files, including the public header.
Example:
public .h file
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass
{
private:
// Just forward declaring in public header.
struct Private;
int x;
public:
void combineWithX(int y);
};
#endif
in .cpp file
#include "SomeClass.h"
// Declare all private member functions of SomeClass here
struct SomeClass::Private
{
static void someHelper(SomeClass& self)
{
self.x = self.x + 1;
}
};
void SomeClass::combineWithX(int y)
{
Private::someHelper(*this);
x += y;
}
I agree that it is a problem that implementation details need to be exposed in a header file; it interferes with separation of interface and implementation.
Moving private helper functions to be free functions in the .cpp file (I presume that is what you meant by "static") won't work if those functions need to access private member variables.
You may be interested to look at the pImpl idiom (more)
Sometimes I see people using two different headers, a public header and a private one, like this:
// SomeClass.h - - - -
SomeClass
{
public:
// public functions
}
// SomeClass_.h - - - -
SomeClass
{
public:
// public functions
private:
// private functions
}
// SomeClass.cpp - - - -
#include "SomeClass_.h"
// SomeClass implementation
This has the advantage of a public header that isn't cluttered with private function declarations, but it requires the developer to maintain 3 copies of each function signature.
Header files have long been recognized by many as being problematic in general, not only because of the added maintenance overhead associated with them, but also because of the effect they have on the build environment. It's easy to write code or set build settings that cause a cascade of system or external headers to fail to compile, resulting in a large number of potentially obscure errors. C++20 Modules are an alternative that may be worth exploring.
Related
Suppose we need to write a library of functions which we intend to use in our programs, then we could write it by the following way.
In a .h file we declare the function (mylibrary could be any file name we wish)
Assuming sum is the function we wish to have in our library
int sum(int x, int y);
Then we will have a .cpp file which will define the function as follows :
#include "mylibrary.h"
int sum(int x, int y){ return x+y; }
Now we we wish to use this function in our programs, say myprog.cpp, we could use like this :
#include
#include "mylibrary.h"
int main()
{
cout<<sum(10,20)<<endl;
return 0;
}
My question is that can we do something similar for classes as we did for functions, i.e.
Can we declare classes in a .h file like :
class X;
class Y;
Then define the class in .cpp like :
#include"myclasses.h"
class X
{
public:
int m;
};
class Y
{
public:
int n;
};
and then use these classes in our program, say myprog.cpp, like this :
#include"myclasses.h"
int main()
{
class X myX;
myX.m = 0;
return 0;
}
I tried this and got Error aggregate 'X myX' has incomplete type and cannot be defined.
If I put entire definition in myclasses.h file, then it runs fine without errors.
You can put all of the methods in the .cpp file, but you have to have a "complete" declaration of the class in the header file. That is, you can do this:
// X.h
#ifndef _X_H
#define _X_H
class X {
int data;
void internal_method();
public:
void foo();
void bar();
};
#endif // X.h
and then you can define X::foo, X::bar, and X::internal_method in a .cpp file, but you can't do this or anything like it:
// X.h
#ifndef _X_H
#define _X_H
// This code is incorrect and will not even compile
class X;
public void X::foo();
public void X::bar();
#endif // X.h
This is a fundamental limitation of C++, and yes, it means you can't change the data members or add or remove methods - even private methods - without recompiling everything. The pimpl hack works around this, but has its own problems.
(You may have noticed that class X; all by itself is a valid thing to write. That is an "incomplete" declaration of the class, which allows you to declare things involving pointers and references to X objects, but not X objects themselves. For instance, this header file is valid:
// Y.h
#ifndef _Y_H
#define _Y_H
class X;
class Y {
X& ex;
public:
Y(X& ex) : ex(ex) {}
void foo();
void bar(X& fx);
};
#endif // Y.h
This can be a useful thing to do, for instance to cut down on the number of header files that need to include other header files, and to break mutual dependency loops (imagine if class X had some methods that took reference-to-Y arguments, without a feature like this you couldn't write that at all).)
Yes, you can do this; but the complete declaration of a class — analogous to declaring a function — involves declaring all of its members. (See http://en.cppreference.com/w/cpp/language/class for details, though I gather that you're already familiar with them.)
If you simply "forward declare" the class, by writing class Foo; without fully declaring it, then you can still pass around pointers to it, but you can't refer to any of its members, including its constructors (even the compiler-generated ones, because those aren't unconditionally generated; not all classes have them). Note that a forward declaration isn't even enough to tell the compiler how big an instance will be (sizeof).
I wish to compile part of my code as a static library to include in other project. Of course I'll have to distribute the compiled library and an header file containing the class declaration and the public members, but I don't know if it's possible to move all private members and declarations to a place different than the header file.
Example:
In the project.h file:
class MyClass
{
public:
MyClass();
void Give_me_an_input(int);
int Get_your_output();
private:
int a, b;
int MySecretAlgorithm();
};
In the .cpp file:
MyClass::MyClass()
{
a = 1;
b = 0;
}
void MyClass::Give_me_an_input(int c)
{
b = c;
}
int MyClass::Get_your_output()
{
return MySecretAlgorithm();
}
int MyClass::MySecretAlgorithm()
{
return (a + b);
}
Is there a way to move all private members int a, b; and int MySecretAlgorithm(); to a place different than the header file?
The pointer to implementation idiom can be used in such a scenario, commonly referred to as pimpl.
The basic idea is to take the implementation details out of the declaration
and simply have an opaque pointer to the implementation details.
std::unique_ptr is used in the the following example; but you could of course just use normal pointers.
// my_class declaration unit.
class my_class {
private:
class impl;
unique_ptr<impl> pimpl;
public:
};
// my_class implementation unit
class my_class::impl {
int whatever;
int whenever;
};
my_class::my_class(): pimpl( new impl )
{
}
Over the years I've seen some hacks to do this, but I don't think they are worth it. If your library is reasonably 'chunky' (ie: no method is being called a billion times a microsecond); and you can re-write chunks of your code...
You might consider making all the public stuff an abstract class (all virtual = 0) and then deriving your concrete classes from it.
Down sides of this:
- All your public calls become virtual (some optimizations can bypass this, but not often).
- You can't 'new up' your classes anymore, you'll need to implement a factory pattern.
The problem with any of the other hacks I'm familiar with is that they basically declare the methods in one set of headers, and then redeclare the same things with the 'real' implementation in private headers - depending on the linker to match up the names. A couple problems here are:
Maintaining this mess sucks. You can't use an #ifdef because it sounds like you want to physically hide your implementation. So you have dual maintaining, or a build step that generates your public headers.
Can only be used via pointer. You have to play games making constructors private and still have a factory because the compiler won't generate structs of the right size if you let the client gen it by value (or even with new).
Finally, I once saw a hack where the programmer tried to declare a byte array in the private area of the 'public' class so that the client code could still declare by value or 'new' it themselves. This suffers all the previous problems, plus you probably don't want to have to 'know' the size of the structs since they depend on packing and alignment. Your 'build step' would more or less have to have a runtime component that used sizeof() - and now you have a versioning problem if you want to change the size of the struct/class.
I came across an implementation which had the pimpl class as a header and included that in the pimpl implementation. Does it even make sense? Something like this:
UI.h
class UI {
public:
UI();
virtual ~UI();
// bunch of methods
private:
UIImpl* m_impl;
}
UIImpl.h
class UIImpl
{
public:
UIImpl( ...) ;
......
}
UIImpl.cpp
#include "UIImpl.h"
UIImpl::UIImpl()
{
//Actual Implementation
...
}
I was thinking that the reason for PIMPL was to hide the implementation totally inside the cpp file. Does having a header defeat the purpose?
They're different kinds of header. UI.h is "public" - it's part of the external interface of the library, for use by its clients.
UIImpl.h is "private," just as the UIImpl.cpp is. As long as it's never included in a public header, it can remain invisible to clients, just as the .cpp itself can.
There can be several reasons for splitting the impl class definition into a header file. Perhaps some other implementation classes are passed UIImpl& parameters. Perhaps it's easier to run doxygen on headers only. Perhaps it's just project policy.
The bottom line is, it's still Pimpl, as long as you don't publish the private header.
I was thinking that the reason for PIMPL was to hide the implementation totally inside the cpp file. Does having a header defeat the purpose?
Not necessarily. pIMPL can be used for fast value swapping (probably in architectures before C++11/move semantics), bridge design pattern or any other number of other reasons.
An example of bridge design pattern:
class WinImpl { virtual ~WinImpl() = 0; /* other interfaces here */ };
// different header file(s)
#ifdef WIN32
class WindowsWinImpl: public WinImpl { /* ... */ };
#else
class LinuxWinImpl: public WinImpl { /* ... */ };
#endif
// different header file
class Window { private: WinImpl* pImpl /*= OSWindowFactory::CreateImpl();*/ };
In this case you have a pImpl model, where it is perfectly OK to include the definition of WinImpl in the header of Window class (because the purpose is not to hide the implementation but to abstract it's interface).
It makes perfect sense to do this. It allows the UIImpl.h (and related .cpp) to be modified, without having to change code that is dependent on UI.h. Since the UIimpl class is just stored as a pointer [and presumably the UI itself only has access to public methods of the UIimpl class, nothing about the UIimpl class is known to the UI.h code.
In fact, you probably NEED the "UIimpl.h" to allow the public functionality of the class to be seen by the UI class.
E.g.
class UIImpl
{
public:
UIImpl( ...) ;
void func() { ... }
}
class UI
{
public:
UI();
virtual ~UI();
// bunch of methods
void func() { m_impl->func(); }
...
}
For this to work, UI needs to know the public interface provided by the UIimpl class.
Yes, it does make sense.
An example of use: in code developed for more than one operating system, UI.h would be visible from the operating-system-independent code, but not UIImpl.h. The operating-system-dependent-code (implementation code) would see both headers, UI.h and UIImpl.h
I have a class:
class M {
public:
static std::string t[];
};
with an initialization that comes later. I want to use the M::t later in a different class (header file):
class Use {
public:
void f() { std::cout << M::t[0] << std::endl; }
};
Is there any way to achieve this without including the whole class M for the header file of the Use? I understand that forward declarations do not allow accessing class members, however this beauty is a static one, so it shouldn't be a huge problem for the compiler..
No, you can't. You can either include the header in the header, or separate the implementation Use::f in an implementation file and include M's header there.
There are no partial classes like in C#, where you can define a class in several files.
Since you are making it a public static member, why don't you create a namespace and embed it there?
namespace myns{
std::string t[];
}
You can access it from anywhere then, just like you would have done with a public static class member.
Forward declarations only allow you to use forward-declared-class pointers or references, not members! If you want to use class members like in your example you have to include the class header, even if it's static.
Here is the solution if you don't want to include M.h in your Use.h header:
Use.h
class Use {
public:
void f();
};
Use.cpp
#include "M.h"
#include "Use.h"
void Use::f() {
std::cout << M::t[0] << std::endl;
}
Also, you have to know it's a bad habit to write code in header files, except of course for inline and templates.
I want to make two classes: an object and an object_manager, but I'm confused about how they should see/include each other. I've heard that it's forbidden for two headers to include each other and if my code dependencies has circles then it's a bad code design and usually it should be like a hierarchy structure (town->house->furniture and furniture shouldn't know about town existence).
But here I have the object_manager which knows and holds all the objects, and the objects should have an option to create new objects, but then they should call the object_manager which will force them to know about it existence and this will create a circle in the structure, which is bad.
It's like one process wants to create a new process by calling the OS system calls, so the OS and the process knows about each other.
Is there a way I can implement this in the right code design, or should it just be bad sometimes?
I thought maybe the objects should have a special place where they will store all their "system calls", and the object_manager will check it from time to time, but maybe there is a better way.
Use forward declaration:
class ObjectManager;
class Object
{
private:
ObjectManager* m_objManager;
....
public:
....
};
In .cpp file you can include the ObjectManager.h
Also instead of ObjectManager make the interface which will give you more abstraction for implementation IObjectManager.
Actually it is possible to implement the two. And no it's not really bad. Here is some partial code.
let's say you have a header file
myobject.h
#ifndef _MYOBJECT
#define _MYOBJECT
// Declare the Object Manager class in it.
class MyObjectManager; // forward declaration
class MyObject {
MyObjectManager manager;
registerSelf(MyObjectManager &m);
}
#endif _MYOBJECT
Now for the ObjectManager header
#ifndef _MYOBJECT_MANAGER
#define _MYOBJECT_MANAGER
class MyObject; // forward declaration
class MyObjectManager {
private:
List list[];
public:
registerObject(MyObject &o);
};
#endif
Implementation of objectmanager
#include <myobject>
#include <myobjectmanager>
MyObjectManager::manageMyObject(MyObject &o) {
list += o; /* etc. */
}
Implementation of object
#include <myobject>
#include <myobjectmanager>
MyObject::registerSelf(MyObjectManager &manager) {
this.manager = manager;
manager.registerObject(*this);
}
There are many cases where classes need to know about each other. The only issue with this is they have to know about each other partially or at least one class does. The way the issue is generally solved is using forward declarations . The only sticky issue is in class A you can't declare a member that has a type of class B only a pointer or a reference to Class B.
class B;
class A
{
B* oB;
};
class B
{
A oA;
}:
Some general recommendations to remove the coupling between headers follow:
Forward Declare what you can. Sometimes your A class uses others classes (X,Y,..) only by passing references or pointers. So in your A.h you can declare methods that use these X,Y return or argument types without the compiler needing to know the complete type. That means that A.h does not need to include X.h or Y.h
Use PImpl idioms, Sometimes the best way to decouple implementation from interface (without using virtual or abstract classes) is doing something like:
Foo.h
class Foo {
struct Impl;
Impl* m_impl;
public:
Foo();
void SomeMethod();
}
Foo.cpp
#include "X.h"
struct Foo::Impl {
/* actual implementation */
...};
Foo::Foo() : m_impl( new Foo::Impl() ) {};
void Foo::SomeMethod() {
m_impl->SomeMethod();
}
What you're describing is an object that can only exist inside another object.
A good way to implement this is with nested classes:
class object_manager {
public:
class object { // object_manager::object. public allows it to be used outside of manager
public:
void foo() {
object* t = construct(); // can call object_manager methods
}
};
private:
object my_objects[5]; // can create objects
static object* construct() { return NULL; }
};
Keep in mind that you can still have 2 cpp files for object and object_manager.
The CPP files can include each other's headers without causing a compile problem (whether it's correct from a design point of view is a different matter, but should be ok in yur case). This means they can call each other's methods, etc.
Regarding the header files, the "object manager" header will most likely include the "object" header because the "object manager" class needs to work with "object" class instances. If the "object" header file needs to know about the "object manager" class, place a forward declaration for the "object manager" in the "object" header file. That way you can use pointers and references to the "object manager" in the "object" header file without creating a circular include dependency.