Могу ли я объявить имена, определенные в другом заголовке, в файлах заголовков? - PullRequest
0 голосов
/ 07 мая 2020

Я хочу создать класс Student, который имеет член библиотеки типов std::string, но я не хочу включать заголовок <string> в свой Student.h и использовать только предварительное объявление:

// 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)
{}
  • Когда я компилирую программу, я получаю следующие ошибки: ../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) :

  • Итак, могу ли я использовать форвардное объявление, чтобы в заголовке не было не включаю какой-либо заголовок, а просто объявляю вперед-назад для типов, которые мне нужны, а затем в исходный код я включаю заголовки?

  • Я сделал это, потому что читаю книгу Гийома «Освоение Qt5» Lazar, в котором он привел этот пример:

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

«Синтаксис typedef struct _FILETIME FILETIME - это своего рода предварительное объявление для синтаксиса FILENAME. Поскольку мы используем только ссылку, мы можем избежать включения тег в нашем файле SysInfoWindowsImpl.h и сохраните его в файле CPP. " из книги.

  • Так может кто-нибудь объяснить мне, как он мог использовать typedef struct _FILETIME, которое определено в windows.h? Спасибо.

Ответы [ 2 ]

3 голосов
/ 07 мая 2020

Да, но только если они совпадают.

Вы пересылаете объявленный глобальный тип string, а не в пространстве имен std.

Вероятно, вы могли бы сделать он работает с namespace std {}, но тогда ваша программа будет иметь неопределенное поведение, потому что вам не разрешено объявлять новые вещи в этом пространстве имен (за некоторыми исключениями).

В общем, вы хотите избежать предварительных объявлений для чего угодно, кроме ваших собственных классов.

Просто #include <string>. Если это вызывает проблемы, вам следует решить их самостоятельно.

0 голосов
/ 07 мая 2020

Нет, нельзя сегодня (в мае 2020 г.). См. Также this и n3337 (стандарт C ++ 11).

Но C ++ 20 или более поздняя версия может добавлять модули и тогда все становится иначе.

Практически, для небольшой программы (например, менее нескольких десятков тысяч строк вашего кода C ++) общий подход состоит в том, чтобы иметь один файл заголовка, который вы должны были бы #include в каждой из ваших единиц перевода, и этот общий главный файл заголовка будет #include многими стандартными заголовками. С недавним G CC вы можете использовать предварительно скомпилированные заголовки (и практически говоря, это лучше всего работает с одним главным заголовком, возможно, с #include -ing файлами подзаголовков; см. это объяснение)

Рассмотрите также возможность использования достаточно хорошего набора инструментов автоматизации сборки . На Linux это может быть комбинация G CC или Clang , ccache , с make или ниндзя , эт c ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...