一世轻尘 发表于 2021-5-13 11:20:26

C++分散编译问题

C++调用类头文件为什么只需要include声明部分而不需要类的定义部分
比如C++中新建一个r.h的头文件 ,并在头文件中声明了一个类,
然后添加一个源文件r.cpp来定义这个类,定义中使用#include “r.h”;
然后再建一个m.cpp中实现主函数,使用#include "r.h",不用#include"r.cpp",就能运行得到结果。

人造人 发表于 2021-5-13 11:29:48

你怎么编译的?这样吗?
g++ -g -Wall -o main m.cpp
这样肯定无法通过编译,会提示你找不到 r.cpp 中的函数

应该是这样
g++ -g -Wall -o main m.cpp r.cpp

一世轻尘 发表于 2021-5-14 20:33:45

人造人 发表于 2021-5-13 11:29
你怎么编译的?这样吗?
g++ -g -Wall -o main m.cpp
这样肯定无法通过编译,会提示你找不到 r.cpp 中的 ...

嗯,这个我知道,不是这个问题
我是在测试分散编译过程中用匿名名称空间来隐藏辅助函数的过程中发现的这个问题,以前没有注意,就是这里有三个文件,接口文件:Dtime.h,实现文件:Dtime.cpp,驱动文件:main.cpp,在Dtime.cpp文件中我定义了一个辅助函数readHour来辅助实现Dtime.h中声明的类的一些方法,这个函数没有被用户访问的必要,所以把它放在Dtime.cpp的匿名名称空间里面.然后在主函数里定义了另一个同名readHour函数,此时我用include"Dtime.cpp"的时候,发现出现了readHour重复定义的问题,
然后我就发现书中的main文件只包含了#include"Dtime.h"接口文件,而没有include"Dtime.cpp"文件.所以就想问主函数里为什么可以不用include"Dtime.cpp",如果没有这条语句,那Dtime.h文件里声明的函数不就都没有定义了吗,为什么程序还是可以运行,程序是怎么知道从哪里去找头文件中函数的实现的?

我用的是vscode,下面是其中的tasks.json文件,之前我是用注释掉的哪一行语句来直接编译所有该目录下所有文件的,所以没发现这个问题,现在换成第10行和第12行的那两条语句,编译了Dtime.cpp文件,但主函数中并没有#include"Dtime.cpp",那它们是怎么连接的

一世轻尘 发表于 2021-5-14 20:37:05

人造人 发表于 2021-5-13 11:29
你怎么编译的?这样吗?
g++ -g -Wall -o main m.cpp
这样肯定无法通过编译,会提示你找不到 r.cpp 中的 ...

这是三个文件的内容
Dtime.h:
#ifndef DTIME_H
#define DTIME_H

#include <iostream>
using std::istream;
using std::ostream;

namespace DTimeSavitch
{
    class DigitalTime
    {
    public:
      DigitalTime(int theHour, int theMinute);
      DigitalTime();

      int getHour() const;
      int getMinute() const;

      void advance(int minutesAdded);
      void advance(int houtsAdded, int minutesAdded);
      friend bool operator==(const DigitalTime &time1, const DigitalTime &time2);
      friend istream &operator>>(istream &ins, DigitalTime &theObject);
      friend ostream &operator<<(ostream &outs, const DigitalTime &theObject);

    private:
      int hour;
      int minute;
    };
}
#endif
Dtime.cpp:
#include <iostream>
#include <cctype>
#include <cstdlib>
using std::cin;
using std::cout;
using std::istream;
using std::ostream;
#include "Dtime.h"

namespace
{
    int digitToInt(char c)
    {
      return (int(c) - int('0'));
    }

    void readMinute(int &theMinute)
    {
      char c1, c2;
      cin >> c1 >> c2;
      if (!(isdigit(c1) && isdigit(c2)))
      {
            cout << "Error: illegal input to reaadMinute\n";
            exit(1);
      }

      theMinute = digitToInt(c1) * 10 + digitToInt(c2);

      if (theMinute < 0 || theMinute > 59)
      {
            cout << "Error: illegal input to readMinute\n";
            exit(1);
      }
    }

    void readHour(int &theHour)
    {
      char c1, c2;
      cin >> c1 >> c2;
      if (!(isdigit(c1) && (isdigit(c2) || c2 == ':')))
      {
            cout << "Error: illegal input to readHour\n";
            exit(1);
      }
      if (isdigit(c1) && c2 == ':')
      {
            theHour = digitToInt(c1);
      }
      else
      {
            theHour = digitToInt(c1) * 10 + digitToInt(c2);
            cin >> c2;
            if (c2 != ':')
            {
                cout << "Error: illegal input to readHour\n";
                exit(1);
            }
      }
      if (theHour == 24)
            theHour = 0;
      if (theHour < 0 || theHour > 23)
      {
            cout << "Error: illegal input to readHour\n";
            exit(1);
      }
    }
}

namespace DTimeSavitch
{
    istream &operator>>(istream &ins, DigitalTime &theObject)
    {
      readHour(theObject.hour);
      readMinute(theObject.minute);
      return ins;
    }
    ostream &operator<<(ostream &outs, const DigitalTime &theObject)
    {
      outs << theObject.hour << ':';
      if (theObject.minute < 10)
            outs << '0';
      outs << theObject.minute;
      return outs;
    }
    bool operator==(const DigitalTime &time1, const DigitalTime &time2)
    {
      return (time1.hour == time2.hour && time1.minute == time2.minute);
    }
    DigitalTime::DigitalTime(int theHour, int theMinute)
    {
      if (theHour < 0 || theHour > 24 || theMinute < 0 || theMinute > 59)
      {
            cout << "Illegal argument to DigitalTime constructor.";
            exit(1);
      }
      else
      {
            hour = theHour;
            minute = theMinute;
      }
      if (hour == 24)
            hour = 0;
    }
    DigitalTime::DigitalTime()
    {
      hour = 0;
      minute = 0;
    }
    int DigitalTime::getHour() const
    {
      return hour;
    }
    int DigitalTime::getMinute() const
    {
      return minute;
    }
    void DigitalTime::advance(int minutesAdded)
    {
      int grossMinutes = minute + minutesAdded;
      minute = grossMinutes % 60;
      int hourAdjustment = grossMinutes / 60;
      hour = (hour + hourAdjustment) % 24;
    }
    void DigitalTime::advance(int hoursAdded, int minutesAdded)
    {
      hour = (hour + hoursAdded) % 24;
      advance(minutesAdded);
    }
}
main.cpp:
#include <iostream>
#include "Dtime.h"

void readHour(int &theHour);

int main()
{
    using std::cin;
    using std::cout;
    using std::endl;

    using DTimeSavitch::DigitalTime;
    int theHour;
    readHour(theHour);
    DigitalTime clock(theHour, 0), oldClock;

    oldClock = clock;
    clock.advance(15);
    if (clock == oldClock)
      cout << "Sometheing is wrong.";
    cout << "You entered " << oldClock << endl;
    cout << "15 minutes later the time will be " << clock << endl;
    clock.advance(2, 15);
    cout << "2 hours and 15 minutes after that\n"
         << "the time will be " << clock << endl;
    return 0;
}

void readHour(int &theHour)
{
    using std::cin;
    using std::cout;
    cout << "Let's play a time game.\n"
         << "Let's pretend the hour has just changed.\n"
         << "You may write midnight as either 0 or 24,\n"
         << "but, I will always write it as 0.\n"
         << "Enter the hour as a number(0 to 24)";
    cin >> theHour;
}

人造人 发表于 2021-5-14 20:53:00

一世轻尘 发表于 2021-5-14 20:37
这是三个文件的内容
Dtime.h:



cpp文件是通过命令行传递给编译器的,不是通过 #include 指令添加到另一个cpp文件中的

人造人 发表于 2021-5-14 21:01:58

g++ -g -Wall -o main main.cpp Dtime.cpp
没有报错

一世轻尘 发表于 2021-5-14 21:10:41

本帖最后由 一世轻尘 于 2021-5-14 21:13 编辑

人造人 发表于 2021-5-14 20:53
cpp文件是通过命令行传递给编译器的,不是通过 #include 指令添加到另一个cpp文件中的

懂了,蟹蟹{:10_298:},感觉还是太依赖IDE了
页: [1]
查看完整版本: C++分散编译问题