开发者

Using forward declarations for built in datatypes

开发者 https://www.devze.com 2023-01-02 18:43 出处:网络
I understand that wherever possible we shall use forward declarations instead of includes to speed up the compilation.

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.


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.


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.


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.


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)
 };


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号