c++ headers keeping sane
The biggest problem I seem to run into when coding in c++ is the fact that you must declare a class before you can reference it. Say I have two header file like this...
Header1.h
#include "Header2.h"
#include <deque>
#include <string>
#include <iostream>
using namespace std;
class HelloPackage;
class Hello
{
public:
string Message;
HelloPackage * Package;
Hello():Message("")
{
}
Hello(string message, HelloPackage * pack)
{
Message = message;
Package = pack;
}
void Execute()
{
cout << Message << endl;
//HelloPackage->NothingReally doesn't exist.
//this is the issue essentially
Package->NothingReally(8);
}
};
Header2.h
#include "Header1.h"
#include <deque>
#include <string>
#include <iostream>
using namespace std;
class HelloPackage
{
public:
deque<Hello> Hellos;
HelloPackage()
{
Hellos = deque<Hello>();
}
int Add开发者_运维知识库Hello(string Message)
{
Hellos.push_back(Hello(Message,this));
}
void ExecuteAll()
{
for each(Hello h in Hellos)
h.Execute();
}
int NothingReally(int y)
{
int a = 0;
a += 1;
return a + y;
}
}
What I'm wondering is, is there any elegant solution for dealing with these issues? In say c#, and java, you're not restricted by this "linear" compiling.
- Use header include guards, either "#ifndef / #define / #endif", or "#pragma once"
- Put your code in a .cpp, not inline in the header
- ???
- Profit
The reason this will work for you is because you can then use forward declarations of the class you want to reference without including the file if you so wish.
- You are missing include guards
- why define methods in the header?
Besides these problems with your code, to answer your question : normal way is to forward declare classes - not to include headers in headers (unless you have to).
If you follow a few basic rules, it is not awkward at all. But in comparison to e.g. Java or C#, you have to follow these rules by yourself, the compiler and/or language spec does not enforce it.
Other answers already noted that, but I will recap here so you have it in one place:
Use include guards. They make sure that your header (and thus your class definition) is only included once.
Normally, you will want to separate the declaration and implementation of your methods. This makes the header files more reusable and will reduce compilation time, because the header requires normally fewer #includes than the CPP (i.e. implementation) file.
In the header, use forward declarations instead of includes. This is possible only if you just use the name of the respective type, but don't need to know any "internals". The reason for this is that the forward declaration just tells the compiler that a certain name exists, but not what it contains.
This is a forward declaration of class Bar:
class Bar; class Foo { void foooh(Bar * b); };
Here, the compiler will know that there is a Bar somewhere, but it does not know what members it has.
Use "using namespace xyz" only in CPP files, not in headers.
Allright, here comes your example code, modified to meet these rules. I only show the Hello class, the HelloPackage is to be separated into header and CPP file accordingly.
Hello.h (was Header1.h in your example)
#include <string>
class HelloPackage;
class Hello
{
public:
Hello();
Hello(std::string message, HelloPackage * pack);
void Execute();
private:
string Message;
HelloPackage * Package;
};
Hello.cpp
#include "Hello.h"
#include "HelloPackage.h"
using namespace std;
Hello::Hello() : Message("")
{}
Hello::Hello(string message, HelloPackage * pack)
{
Message = message;
Package = pack;
}
void Hello::Execute()
{
cout << Message << endl;
// Now accessing NothingReally works!
Package->NothingReally(8);
}
One question that may arise is why is the include for string is needed. Couldn't you just forward declare the string class, too?
The difference is that you use the string as embedded member, you don't use a pointer to string. This is ok, but it forces you to use #include, because the compiler must know how much space a string instance needs inside your Hello class.
精彩评论