正确包含标题

Posted

技术标签:

【中文标题】正确包含标题【英文标题】:Including headers correctly 【发布时间】:2013-02-19 14:54:54 【问题描述】:

第一个问题。如果我在第二个类的头文件中包含一个类的头文件,是否必须在第二个类的 .cpp 文件中包含第一个类的头文件?

在第二类的 .cpp 文件中,我包含了它的标题,其中包含第一类的 .h 文件。那么这不是正确的还是我必须将第一个类的头文件也包含到第二个类的 .cpp 文件中?

第二个问题。我有两节课。第一个有静态变量和函数,所以我可以在不创建对象的情况下调用它。在第一堂课我有第二堂课的静态对象。现在在第二类,我想将第一类的一些函数的返回作为操作数传递给第一类的函数。在第二节课上我没有收到错误,但是在我之前在第一节课中提到的静态对象的声明中出现了错误。为什么会这样?

代码:

头文件:

 /*
  * NTPlib.h
  *
  *  Created on: 13 Feb 2013
  *  Author    : Platonas
  */

#ifndef NTP_H_
#define NTP_H_

#include "Arduino.h"
#include "SPI.h"
#include "IPAddress.h"
#include "EthernetUdp.h"
#include "Ethernet.h"
#include "DayNumber.h"

class NTP 
    private:

    public:
        static EthernetUDP Udp;
        static DayNumber DN;

        static const int Gmt = 2;
        static const unsigned int localPort = 8888;
        static const int NTP_PACKET_SIZE = 48;

        static byte packetBuffer[NTP_PACKET_SIZE ];

        static unsigned long secsSince1900;
        static unsigned long UnixTime;
        static int utchour;
        static int lcthour;
        static int min;
        static int sec;
        static int year;
        static int month;
        static int date;
        static int dayOfWeek;
        static bool timeSet;

        NTP();
        static NTP getTime();
        static bool testNtpServer();
        static void startEthernetAndUdp();
        static unsigned long sendNTPpacket(IPAddress& address);
        static int getYear();
        static int getMonth();
        static int getDate();
        static int getDayOfWeek();
        static int getUTChour();
        static int getLCThour();
        static int getMin();
        static int getSec();
        static void serialPrinting();

        virtual ~NTP();
;

#endif /* NTPLIB_H_ */

    /*
      DayNumber.h - Library for calculation of day's number on 1 and 4 years loop.
      Created by Pavlidis Kyriakos, December 20, 2012.
      Released into the public domain.
    */

    #ifndef DayNumber_H_
    #define DayNumber_H_

    #include "NTP.h"

    class DayNumber 

        private:
            int _day1YearLoop[];
            int _day4YearLoop[];

        public:

            int Days1YearLoop;
            int Days4YearLoop;

        DayNumber();
        void dayNumberCalc();
        virtual ~DayNumber();

        bool checkLeapYear(int setYear);
    ;

#endif

.cpp 文件:

/*
  NTP.cpp - Library for NTP server.
  Created by Pavlidis Kyriakos, Feb 13, 2013.
  Released into the public domain.
*/

#include "NTP.h"
#include "DayNumber.h"

unsigned long NTP::UnixTime = 0;
unsigned long NTP::secsSince1900 = 0;
int NTP::utchour = 99;
int NTP::lcthour = 99;
int NTP::min = 99;
int NTP::sec = 99;
int NTP::year = 99;
int NTP::month = 99;
int NTP::date = 99;
int NTP::dayOfWeek = 99;
byte NTP::packetBuffer[NTP_PACKET_SIZE ];
bool NTP::timeSet = false;
DayNumber NTP::DN = DayNumber();
EthernetUDP NTP::Udp = EthernetUDP();

NTP::NTP() 
    // TODO Auto-generated constructor stub


NTP NTP::getTime() 

    if (testNtpServer()) 
        timeSet = true;

        // We've received a packet, read the data from it
        Udp.read((unsigned char*)packetBuffer,NTP_PACKET_SIZE);  // Read the packet into the buffer

        // The timestamp starts at byte 40 of the received packet and is four bytes,
        // or two words, long. First, extract the two words:
        unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
        unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);

        // Combine the four bytes (two words) into a long integer.
        // This is NTP time (seconds since Jan 1 1900):
        secsSince1900 = highWord << 16 | lowWord;

        // Now convert NTP time into everyday time:
        // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
        const unsigned long seventyYears = 2208988800UL;

        // Subtract seventy years:
        UnixTime = secsSince1900 - seventyYears;

        sec = UnixTime % 60;

        //Calc min
        min = (UnixTime/60)%60;

        //Calc hour
        utchour = (UnixTime/3600)%24;
        lcthour = utchour + Gmt;

        //Day of the week
        dayOfWeek = (((UnixTime/86400UL) + 3) % 7) + 1; //Setting first day Sunday = 1

        //Calculating years
        unsigned long UnixTimeToDays = UnixTime/86400UL;
        //Serial.println(UnixTimeToDays);
        unsigned long calcDaysInYears = 0;
        int calcYear = 1970;
        while((calcDaysInYears += (DN.checkLeapYear(calcYear)? 366:365)) <= UnixTimeToDays) 
            calcYear++;
        
        year = calcYear;

        //Calculating days in this year
        calcDaysInYears -= (DN.checkLeapYear(calcYear)? 366:365);
        int daysPassedInYear = UnixTimeToDays - calcDaysInYears;

        //Set DayNumber one year loop
        DN.Days1YearLoop = daysPassedInYear + 1;

        //calculating date and month
        static const uint8_t monthDays[] = 31,28,31,30,31,30,31,31,30,31,30,31;
        int calcMonth;
        int monthLength;

        for (calcMonth = 0; calcMonth<12; calcMonth++) 
            if (DN.checkLeapYear(year)) 
                monthLength = (calcMonth == 1) ? 29: 28;
            
            else 
                monthLength = monthDays[calcMonth];
            
            if ( daysPassedInYear > monthLength) 
                daysPassedInYear -= monthLength;
            
            else 
                break;
            
        
        month = ++calcMonth;
        date = ++daysPassedInYear;

        serialPrinting();

        return NTP();
    
    else 
        //Error me tous ntp diavazoume wra apo DS1307
        Serial.println("pame gia RTC");
        return NTP();
    


unsigned long NTP::sendNTPpacket(IPAddress& address) 
  // Set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);

  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // Eight bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // All NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket();


void NTP::startEthernetAndUdp() 
    //Declaration of the mac address of ethernet shield
    byte mac[] = 0x00,0xAA,0xBB,0xCC,0xDE,0x02;
    if (Ethernet.begin(mac) == 0) 
        Serial.println("Failed to configure Ethernet using DHCP");
        // No point in carrying on, so do nothing forevermore:
        //for(;;)
        //    ;
        //Prepei na diorthwthei na kanei bypass to DHCP kai na paei sto RTC an den exei internet
    
    Udp.begin(localPort);


bool NTP::testNtpServer() 
    //(193,93,167,241 ); //GR time server on athens ntp.asda.gr
    //(129,215,160,240 ); //UK extntp0.inf.ed.ac.uk School of Informatics, University of Edinburgh, Scotland, UK
    //(138,195,130,71 ); //FR ntp.via.ecp.fr VIA, Ecole Centrale Paris, France
    //(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server
    //(193,93,167,239); //GR time server on athens ChronosAsdaGr
    //(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server
    //(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server

    byte serverslist[4][4] = 
            193,93,167,241,
            129,215,160,240,
            138,195,130,71,
            132,163,4,101
    ;
    IPAddress ntpServers(serverslist[0]);
    sendNTPpacket(ntpServers);
    int x = 0;
    delay(1000);

    //Checking different NTP server if someone is down
    while(!Udp.parsePacket() && x <= 3) 

        //Have to check parsePacket return.
        x++;
        IPAddress ntpServers(serverslist[x]);
        sendNTPpacket(ntpServers);
        delay(1000);
    

    switch (x) 
        case 0:
            Serial.println("1st NTPServer working");
            return true;
            break;
        case 1:
            Serial.println("2st NTPServer working");
            return true;
            break;
        case 2:
            Serial.println("3st NTPServer working");
            return true;
            break;
        case 3:
            Serial.println("4st NTPServer working");
            return true;
            break;
        default:
            Serial.println("All NTP Servers are Down");
            return false;
    


int NTP::getYear() 
    do 
        getTime();
     while(timeSet == false);
    return year;


int NTP::getMonth() 
    do 
        getTime();
    while(timeSet == false);
    return month;


int NTP::getDate() 
    do 
        getTime();
     while(timeSet == false);
    return date;

int NTP::getDayOfWeek() 
    do 
        getTime();
     while(timeSet == false);
    return dayOfWeek;

int NTP::getUTChour() 
    do 
        getTime();
     while(timeSet == false);
    return utchour;

int NTP::getLCThour() 
    do 
        getTime();
     while(timeSet == false);
    return lcthour;

int NTP::getMin() 
    do 
        getTime();
     while(timeSet == false);
    return min;

int NTP::getSec() 
    do 
        getTime();
     while(timeSet == false);

    return sec;


void NTP::serialPrinting() 

    //Serial.PRINTS
    //print seconds since 1900
    Serial.print("Seconds since Jan 1 1900 = " );
    Serial.println(secsSince1900);

    // print Unix time:
    Serial.print("Unix time = ");
    Serial.println(UnixTime);

    //print year
    Serial.print("the year is :");
    Serial.println(year);

    //print month
    Serial.print("Month is : ");
    Serial.print(month);

    //print date
    Serial.print(" Date is: ");
    Serial.println(date);

    //print dayOfWeek
    Serial.print("the day is : ");
    Serial.println(dayOfWeek);

    //printnumber of days that passed in this year (this day counts DayNumber object)
    Serial.print("This day is the number:");
    Serial.println(DN.Days1YearLoop);

    //print Local Time Hour
    Serial.print("The LTC time is ");
    Serial.println(lcthour);

    // Print the hour, minute and second:
    Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
    Serial.print(utchour); // Print the hour (86400 equals secs per day)
    Serial.print(':');

    if ( min < 10 ) 
        // In the first 10 minutes of each hour, we'll want a leading '0'.
        Serial.print('0');
    
    Serial.print(min); // Print the minute (3600 equals secs per minute)
    Serial.print(':');

    if ( sec < 10 ) 
        // In the first 10 seconds of each minute, we'll want a leading '0'.
        Serial.print('0');
    
    Serial.println(sec); // Print the seconds

NTP::~NTP() 
    // TODO Auto-generated destructor stub

/*
  DayNumber.cpp - Library for Calculation of Day's Number on 1 and 4 years loop.
  Created by Pavlidis Kyriakos, December 20, 2012.
  Released into the public domain.
*/

#include "DayNumber.h"


DayNumber::DayNumber() 



void DayNumber::dayNumberCalc() 

    int setYear = NTP::getYear();
    int setMonth = NTP::getMonth();
    int setDay = NTP::getDate();

    //Days that passed from the begging of the year for the 1st Day each Month
    int _day1YearLoop[] = 0,31,59,90,120,151,181,212,243,273,304,334;
    //i = _day1YearLoop;

    //Days that passed from the beginning of the second Year since the for the 1st Day of the running Year in 4 years loop.
    int _day4YearLoop[] = 366,731,1096;

    if (checkLeapYear(setYear)) 
        if (setMonth>2)  //Diorthwsi gia ton mina flebari
            Days1YearLoop = *(_day1YearLoop+(setMonth-1)) + setDay + 1;
            Days4YearLoop = Days1YearLoop;
        
        else 
            Days1YearLoop = *(_day1YearLoop+(setMonth-1)) + setDay;
            Days4YearLoop = Days1YearLoop;
        
    
    else 
        Days1YearLoop = *(_day1YearLoop + (setMonth-1)) + setDay;
        switch (setYear%4) 
            case 1:
                Days4YearLoop = *(_day4YearLoop) + Days1YearLoop;
                break;
            case 2:
                 Days4YearLoop = *(_day4YearLoop+1) + Days1YearLoop;
                 break;
            case 3:
                Days4YearLoop = *(_day4YearLoop+2) + Days1YearLoop;
                break;
            Default:;
                break;
        
    



DayNumber::~DayNumber() 



bool DayNumber::checkLeapYear(int setYear) 
    if (setYear%4 == 0) 
        return true;
    
    else 
        return false;
    

错误出现在 NTP.h 的第一个标题中

描述资源路径位置类型 'DayNumber' 没有命名类型 NTP.h /NTP/lib 第 24 行 C/C++ 问题

它不理解对象的声明。

【问题讨论】:

您应该尝试提供sscce。目前,您有很多不必要的代码。 This Q&A会回答关于头文件相互包含的问题(DayNumber.hNTP.h 如果 NTP 完全是静态的,那么使用命名空间和免费函数会更好。 【参考方案1】:

包含当前文件所依赖的所有文件始终是一个好习惯。假设您更改了“DayNumber.h”,使其不再需要“NTP.h”,现在您的代码将无法编译。

假设您的文件是本地文件,并且您的计算机内存不是非常低,它只会产生微小的差异。最近有一个关于类似主题的问题,我测量了是否包含一些标题,编译30个左右文件(实际上是SAME文件)之间的区别。在我的机器上运行“好”和“坏”之间的误差幅度比包含标题和不包含标题之间的差异要大得多。

至于您的第二个问题,它实际上是由“DayNumber.h”中不需要的“NTP.h”引起的 - 所以你应该“不包括那个”。但是如果你有一个真实的情况,你有一个类需要知道另一个类,你需要使用前向声明,例如class NTP; - 现在,您可以使用 NTP *NTP &amp; 将指针/引用传递/存储到 NTP 类。在完全定义 NTP 类之前,您仍然不能使用 NTP 类中的内容。

【讨论】:

好吧 DayNumber.cpp 有一个名为 dayNumberCalc 的函数,它运行 NTP 类的 3 个函数,所以如果我不包括 NTP.h 我不能要求 NTP::getYear(); function.it 给出错误。我错过了什么吗? 不,它在“DayNumber.h”中,您不应该包含“NTP.h”。您需要在“DayNumber.cpp”中包含“NTP.h”。 hmmmmm.and 为了更好地理解它。如果我一般在另一个函数中调用一个类的函数并且我不需要该类的对象,我必须包含头文件仅在 .cpp 文件中的第一类。我试过了,现在没问题,但我想如果我想在头文件中包含一个类,我会在头文件中这样做,这样 .cpp 文件就会读取它自己的头文件中包含的所有头文件。从这个解决方案中,我了解到我只能将内容包含在 .cpp 中。这在程序上是正确的还是我的问题的方便解决方案。我不想学习任何冒犯, 我只是不知道你这个解决方案是不是像你对我说的那样:“你的代码是错误的,所以要缝一些针才能工作”或者这是正确的方法 你应该只包含你真正需要的头文件——如果你不在头文件中使用一个类,那么你就不需要包含它。如果你只使用一个类的NAME [即编译器不需要了解类的内容],你可以用“前向声明”(例如class NTP;)告诉编译器“我将在稍后的某个阶段告诉你类里面有什么,但现在,你只需要知道它存在”......并且类之间的循环依赖并不罕见 - 解决方案通常是转发声明一个类。

以上是关于正确包含标题的主要内容,如果未能解决你的问题,请参考以下文章

如何正确计算 jTable 行的高度以确保包含 HTML 的包含 jLabel 完全显示?

正确包含 PHP 中的设计实践 [关闭]

如何检查是不是正确包含 JQuery 库(和具有自己代码的文件)?

选择包含“foo”的属性的正确 XPath 是啥?

包含双指针的单链表的正确名称是啥?

如何正确检查字符串是不是不包含特定单词?