C++:拥有一个头文件有意义吗
C++: is there a point to having a header file?
可能重复:
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行代码——这太棒了(根据经验(!
因此,您的示例不需要分离为头文件和实现文件。
我相信有很多原因,其中最引人注目的是:
- 如果你把一个类放在一个源文件中,然后把这个源文件包括在其他使用的源文件中——它会起作用,但如果有任何东西在类之外,它就不会起作用
- 如果使用该类的其他源文件只包含头文件,而不必解析整个类源文件,那么速度会大大加快
- 循环引用,如果类
A
使用类B
,而类B
使用类A
,则必须使用头文件,这在仅使用源文件时是不可能的(使用模板有一种可能的解决方法,但它很复杂,会给您带来麻烦(
当然,您可以将EVERYTHING放在一个.cc文件中,并对其进行编译&运行,不管有多少个类。是否使用头文件取决于您的目的和习惯。例如,如果您想编写一个共享库并将其发布给其他人,则必须使用头文件。然后,用户可以包含您的头文件并调用您编写的函数。
对于大多数一次性代码—永远不会与任何其他程序或人员共享;那么我同意:跳过创建头文件,将所有代码放在.C
、.cc
、.c++
等文件中
但是,如果类将/应该/可能被重用—通常是许多发展意图的目标—在这个过程中,识别声明部分并将其放在头文件中,以及实现部分并将它放在源代码模式中是一个好主意:最终它可能会成为一个可共享的库。
如果所有内容都在.cc
文件中,并且编译器将该文件视为一个编译单元,那么您将无法在其他文件中使用该文件中定义的类(您将得到一个多重定义的符号错误(。在一个文件中定义所有内容也会显著增加编译时间,尤其是在大型项目中。
到目前为止,所有的答案似乎都是关于语言如何根据规范和当前编译器工作的,但我认为问题是为什么是这样设计的。
在向类中添加方法时,必须将声明放在两个位置,这会浪费编程时间。应该完全可以添加基于代码文件生成头文件的编译器过程,不是吗?如今,稍微长一点的编译时间似乎是一个不错的选择,但事实并非总是如此
目前的系统所做的一件事是让你更好地控制什么在哪里。例如,可能有一些定义是你想要的代码,但你不想被放在任何调用你类的人的头中。
- 在CMakeLists.txt的安装功能中使用.cmake文件有什么用
- 在C++中,使用带有 std::optional 参数的函数<T>来表示可选参数是否有意义?
- API 返回智能指针的 std::optional 以明确指定指针可能为 null 是否有意义?
- 从头开始为应用程序创建 docker 映像是否有意义?
- 使用 fstream 库并在屏幕上打印的文件有问题?
- 在c++中,如果首先禁止默认构造,那么禁止复制构造有意义吗
- sizeof(函数)有意义吗?
- 二进制模式 + 格式化文本操作或文本模式 + 二进制数据操作 - 有意义吗?
- 为什么 MFC .rc 文件有时会在末尾手动插入 \0?
- 插入向量时,使用lambda的返回而不是函数的返回是否有意义?
- 在 C++17 中使用 const std::string& 参数有意义吗?
- C++:包含指令和头文件有什么区别?
- 包含 .h 文件和 c/cpp 文件有什么区别?
- 基础类模板参数的有意义名称
- 内联这个函数,确实有意义
- C++ & C 中的".inc"文件有什么意义?您想在什么情况下使用它?
- 一个只包含一个#include的.cpp文件有什么意义
- 匿名命名空间-在头文件和代码文件中都有意义
- 从逗号分隔的文本文件中创建有意义的数据向量的最佳方法是什么?
- C++:拥有一个头文件有意义吗