Search code examples
c++forward-declaration

Can I forward-declare names -defined in other header in a header files?


I want to create a class Student that has a member of type library std::string but I don't want to include the header <string> in my Student.h and use only forward-declaration:

// Student.h
#ifndef STUDENT_H
#define STUDENT_H

#include <iostream>

typedef class string_ string;

struct Student
{
public:
    Student(const string_&, std::size_t);
    const string_ name()const;
    void setName(const string_&);
    std::size_t age()const;
    void setAge(std::size_t);
private:
    string_* name_ ;
    std::size_t age_;
};

 // Student.cpp
#include "Student.h"
#include <string>

Student::Student(const std::string& str, std::size_t a) :
    name_(&str),
    age_(a)
{}
  • When I compile the program I get these errors: ../src/Student.cpp:13:2: error: no declaration matches ‘Student::Student(const string&, std::size_t)’ 13 | Student::Student(const std::string& str, std::size_t a) :

  • So can I use forward declaration so that in a header I don't include any header but just forward-declare for the types I need then in source I include the headers?

  • I've done this because I'm reading Mastering Qt5 book by Guillaume Lazar in which he gave this example:

    //SysInfoWindowsImpl.h
    #include <QtGlobal>
    #include <QVector>
    #include "SysInfo.h"
    
    
    typedef struct _FILETIME FILETIME;
    
    class SysInfoWindowsImpl : public SysInfo
    {
    public:
        SysInfoWindowsImpl();
        void init() override;
        double cpuLoadAverage() override;
        double memoryUsed() override;
    private:
        QVector<qulonglong> cpuRawData();
        qulonglong convertFileTime(const FILETIME& filetime) const;
    private:
        QVector<qulonglong> mCpuLoadLastValues;
    };
    
    //SysInfoWindowsImpl.cpp
    #include "SysInfoWindowsImpl.h"
    #include <windows.h>
    
    
    SysInfoWindowsImpl::SysInfoWindowsImpl() :
        SysInfo(),
        mCpuLoadLastValues()
    {
    }
    
    void SysInfoWindowsImpl::init()
    {
        mCpuLoadLastValues = cpuRawData();
    }
    
    qulonglong SysInfoWindowsImpl::convertFileTime(const FILETIME& filetime) const
    {
        ULARGE_INTEGER largeInteger;
        largeInteger.LowPart = filetime.dwLowDateTime;
        largeInteger.HighPart = filetime.dwHighDateTime;
        return largeInteger.QuadPart;
    }
    

"The syntax typedef struct _FILETIME FILETIME is a kind of forward declaration for FILENAME syntax. As we only use a reference, we can avoid including the tag in our file SysInfoWindowsImpl.h and keep it in the CPP file." from the book.

  • So can someone explain to me how could he use typedef struct _FILETIME which is defined in windows.h? Thank you.

Solution

  • Yes, but only if they match.

    You forward declared a global type string, not in namespace std.

    You could probably make it work with namespace std {} but then your program would have undefined behaviour, because you're not allowed to declare new things in that namespace (with a few exceptions).

    In general, you want to avoid forward declarations for anything but your own classes.

    Just #include <string>. If doing so is causing problems, you should resolve those independently.