Reputation: 23003
I understand that wherever possible we shall use forward declarations instead of includes to speed up the compilation.
I have a class Person
like this.
#pragma once
#include <string>
class Person
{
public:
Person(std::string name, int age);
std::string GetName(void) const;
int GetAge(void) const;
private:
std::string _name;
int _age;
};
and a class Student
like this
#pragma once
#include <string>
class Person;
class Student
{
public:
Student(std::string name, int age, int level = 0);
Student(const Person& person);
std::string GetName(void) const;
int GetAge(void) const;
int GetLevel(void) const;
private:
std::string _name;
int _age;
int _level;
};
In Student.h, I have a forward declaration class Person;
to use Person
in my conversion constructor. Fine. But I have done #include <string>
to avoid compilation error while using std::string
in the code. How to use forward declaration here to avoid the compilation error? Is it possible?
Thanks.
Upvotes: 2
Views: 2083
Reputation: 523734
Since used string
as
std::string _name;
//^^^^^^^^^ concrete member
the whole structure of string
would be needed, so the declaration must be needed. You must #include <string>
.
Declaration of string
can be omitted possible if you write, e.g.
std::string* _name;
//^^^^^^^^^^ pointer or reference
which you could use a forward declaration, but I still recommend you not to do so, because std::string
is not a simple structure type like Person or Student, but a very complex type involving many templates:
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string { ... };
typedef basic_string<char> string;
If you forward declare it wrongly (e.g. class string;
), the compilation will fail when you actually use it because of conflicting type.
Upvotes: 4
Reputation: 116306
You can only use forward declarations with pointers and references (because these are of a fixed size, independent of the size of the object they refer to). If you use a specific class by value, the compiler needs its full definition (in order to know its exact size), thus forward declaration is not enough.
Thus, if you define Student
like this
class Student
{
public:
...
Student(const Person person);
...
private:
Person person;
};
either of the above class members would force you to #include
Person.h in your header.
You understand well, that forward declaration helps avoiding compilation dependencies, thus reduces compilation time. However, that concerns mainly user-defined headers, because these are the ones that can change frequently. Standard library headers are not going to change, so the saving is not significant in those cases.
Upvotes: 2
Reputation: 1139
Forward declarations are used to reduce include and to resolve cyclic dependencies. But when using forwards in the public or protected interface of your class, you place the burden of including the correct header files to the users of your class.
Beside this, forwarding types defined in the STL may not work as expected. For example, std::string might be defined as typedef basic_string<char> string;
. Declaring it forward with namespace std{ class string;}
will give you a compilation error.
Upvotes: 0
Reputation: 19064
You can only use forward declarations for type identification, such as when you use the declared type in a function/method pointer parameter prototype. If you are going to declare a member variable (i.e. std::string _name;) the compiler needs a little bit more than a forward declaration can give it. For example, if someone does a sizeof(Student) the compiler has to have access to the entire declaration to figure out the size.
Upvotes: 1
Reputation: 1394
Maybe also consider to use inheritance.
#include "Person.h" // i am afraid you need to
class Student : public Person
{
...
protected:
int _level;
// no name and age, that is inhertianced from person
// (if you want to access them from student, you maybe need to make them protected)
};
Upvotes: 0