C++:拥有一个头文件有意义吗

C++: is there a point to having a header file?

本文关键字:文件 有意义 有一个 拥有 C++      更新时间:2023-10-16

可能重复:
C++-.h文件中应该包含什么?

我知道这是一般性的,但我发现两次编码真的很烦人,如果我不必在两个文件(我的.h和.cc(之间浏览,而不是把它们都放在一个文件中,我会发现这会容易得多。

那么,如果有一个头文件的大部分内容必须重写,而其余部分可以放在.cc.中,那么有什么意义呢

代替:

 class VoterData {
    // raw data
    Voter::States state;
    bool vote;
    unsigned int numBlocked;
    // flags
    bool _hasState, _hasVote, _hasNumBlocked;
  public:
    VoterData();
    void reset();
    // getters
    Voter::States getState();
    bool getVote();
    unsigned int getNumBlocked();
    bool hasState();
    bool hasVote();
    bool hasNumBlocked();
    // setters
    void setState(Voter::States state);
    void setVote(bool vote);
    void setNumBlocked(unsigned int numBlocked);
};

和:

/* VoterData */
VoterData::VoterData() {
    reset();
}
void VoterData::reset() {
    _hasState = _hasVote = _hasNumBlocked = false;
}
// getters
Voter::States VoterData::getState() { return state; }
bool VoterData::getVote() { return vote; }
unsigned int VoterData::getNumBlocked() { return numBlocked; }
bool VoterData::hasState() { return _hasState; }
bool VoterData::hasVote() { return _hasVote; }
bool VoterData::hasNumBlocked() { return _hasNumBlocked; }
// setters
void VoterData::setState(Voter::States state) {
    this->state = state;
    _hasState = true;
}
void VoterData::setVote(bool vote) {
    this->vote = vote;
    _hasVote = true;
}
void VoterData::setNumBlocked(unsigned int numBlocked) {
    this->numBlocked = numBlocked;
    _hasNumBlocked = true;
}

为什么我不应该把它全部放在.cc文件中并在那里声明类呢?

C++不会告诉您将代码放在哪里。实际上,在您的情况下,最好使用一个文件:

struct VoterData {
    // raw data
    Voter::States state;
    bool vote;
    unsigned int numBlocked;
    // flags
    bool _hasState, _hasVote, _hasNumBlocked;
    // No getters, setters and other cruft needed
};

如果你的类比我或你的例子更复杂,你会注意到有一个头文件有助于理解你的程序。

在这种情况下,头文件(x.h(将很小(例如20行代码(,而实现文件(x.cc(将很大(例如200行代码,比您的示例类中的代码多得多(。任何人(想了解这个类的作用或如何使用它(都必须查看头文件中的20行代码,而不必查看其他200行代码——这太棒了(根据经验(!

因此,您的示例不需要分离为头文件和实现文件。

我相信有很多原因,其中最引人注目的是:

  1. 如果你把一个类放在一个源文件中,然后把这个源文件包括在其他使用的源文件中——它会起作用,但如果有任何东西在类之外,它就不会起作用
  2. 如果使用该类的其他源文件只包含头文件,而不必解析整个类源文件,那么速度会大大加快
  3. 循环引用,如果类A使用类B,而类B使用类A,则必须使用头文件,这在仅使用源文件时是不可能的(使用模板有一种可能的解决方法,但它很复杂,会给您带来麻烦(

当然,您可以将EVERYTHING放在一个.cc文件中,并对其进行编译&运行,不管有多少个类。是否使用头文件取决于您的目的和习惯。例如,如果您想编写一个共享库并将其发布给其他人,则必须使用头文件。然后,用户可以包含您的头文件并调用您编写的函数。

对于大多数一次性代码—永远不会与任何其他程序或人员共享;那么我同意:跳过创建头文件,将所有代码放在.C.cc.c++等文件中

但是,如果类将/应该/可能被重用—通常是许多发展意图的目标—在这个过程中,识别声明部分并将其放在头文件中,以及实现部分并将它放在源代码模式中是一个好主意:最终它可能会成为一个可共享的库。

如果所有内容都在.cc文件中,并且编译器将该文件视为一个编译单元,那么您将无法在其他文件中使用该文件中定义的类(您将得到一个多重定义的符号错误(。在一个文件中定义所有内容也会显著增加编译时间,尤其是在大型项目中。

到目前为止,所有的答案似乎都是关于语言如何根据规范和当前编译器工作的,但我认为问题是为什么是这样设计的

在向类中添加方法时,必须将声明放在两个位置,这会浪费编程时间。应该完全可以添加基于代码文件生成头文件的编译器过程,不是吗?如今,稍微长一点的编译时间似乎是一个不错的选择,但事实并非总是如此

目前的系统所做的一件事是让你更好地控制什么在哪里。例如,可能有一些定义是你想要的代码,但你不想被放在任何调用你类的人的头中。