Если вы следуете нескольким основным правилам, это совсем не неловко. Но по сравнению, например, с Java или C #, вы должны следовать этим правилам самостоятельно, спецификация компилятора и / или языка не соблюдает его.
Другие ответы уже отмечали это, но я повторю здесь, чтобы вы имели это в одном месте:
Использование включает охрану . Они удостоверяются, что ваш заголовок (и, следовательно, ваше определение класса) включается только один раз.
Обычно вам нужно разделить объявление и реализацию ваших методов. Это делает файлы заголовков более пригодными для повторного использования и сократит время компиляции, поскольку заголовок обычно требует меньше #include, чем файл CPP (т.е. реализация).
В заголовке используйте предварительные объявления вместо include. Это возможно только в том случае, если вы просто используете имя соответствующего типа, но не должны знать какие-либо «внутренние компоненты». Причина этого в том, что предварительное объявление просто сообщает компилятору, что существует определенное имя, но не то, что оно содержит.
Это предварительное объявление класса Bar:
class Bar;
class Foo {
void foooh(Bar * b);
};
Здесь компилятор узнает, что где-то есть Bar, но не знает, какие члены у него есть.
Используйте «using namespace xyz» только в файлах CPP, но не в заголовках.
Хорошо, вот ваш пример кода, модифицированный для соответствия этим правилам. Я только показываю класс Hello, HelloPackage должен быть разделен на заголовок и файл CPP соответственно.
Hello.h (был Header1.h в вашем примере)
#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);
}
Один вопрос, который может возникнуть, заключается в том, зачем нужно включение для строки. Не могли бы вы также просто объявить класс строки?
Разница в том, что вы используете строку в качестве встроенного члена, вы не используете указатель на строку. Это нормально, но это заставляет вас использовать #include, потому что компилятор должен знать, сколько места требуется экземпляру строки внутри вашего класса Hello.