在C#或Java中,同时声明和定义类。在C ++中,规范是分开执行。如果我们将整个类写在一个文件中,例如.cpp文件并将其包含在引用它的文件中,除了延长的编译过程之外,技术上会发生什么样的坏事呢?
答案 0 :(得分:12)
如果MyClass
的实施完全在标题文件MyClass.h
中,则只要有人包含MyClass
,就会包含您需要实施MyClass.h
的任何文件。
如果更改MyClass.h
的任何部分,即使它是微不足道的(例如添加注释甚至是空格),那么包含它的所有文件都必须重新编译,即使接口没有更改。
这些都不适用于玩具项目,但正如您所指出的,当您拥有一个由数百(或数千个等)类文件组成的程序时,单独添加的编译时间使得将实现与接口分离是值得的
例如,如果我有以下内容:
// MyClass.h
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include "Inventory.h"
class MyClass
{
public:
MyClass();
void processInventory(Inventory& inventory)
{
// Do something with each item in the inventory here
// that uses iostream, iomanip, sstream, and string
}
private:
// ...
};
它会更加理想地写成:
// MyClass.h
class Inventory;
class MyClass
{
public:
MyClass();
void processInventory(Inventory& inventory);
private:
// ...
};
// MyClass.cc
#include "MyClass.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include "Inventory.h"
MyClass()::MyClass()
{
}
void MyClass()::processInventory(Inventory& inventory)
{
// Do something with each item in the inventory here
// that uses iostream, iomanip, sstream, and string
}
注意:包含MyClass.h
并不意味着必须解析iostream
,iomanip
,sstream
,string
或Inventory.h
。更改processInventory
的工作方式并不意味着必须重新编译使用MyClass.h
的所有文件。
注意现在弄清楚如何使用MyClass
会更容易。头文件有一个重要目的:它们向人们展示如何使用你的课程。使用修改后的MyClass.h
,可以轻松查看功能列表。如果在标题中定义了每个函数,那么您不能仅查看函数列表。这使得弄清楚如何使用该类更加困难。
答案 1 :(得分:5)
您可以打破one definition rule。
如果你这样写:
class foo
{
public:
void doit();
};
foo::doit() {}
并将其包含在多个类中,您将拥有foo::doit
的多个定义,并且您的链接将失败。
但是如果你把你的所有类都内联,可以在类声明中定义它们:
class foo
{
public:
void doit() {
}
};
或明确地将它们内联:
class foo
{
public:
void doit();
};
inline void foo::doit() {}
然后您可以根据需要多次包含该文件。
答案 2 :(得分:2)
当您尝试组合多个此类对象时,链接器将看到该类成员的多个定义。因此,您将无法从包含多个位置的任何内容的源文件生成二进制文件。
答案 3 :(得分:1)
通常,您将类的声明和定义分开。这允许您通过简单地包含声明来在不同的源文件中使用您的类。
如果你将包含声明和定义的.cpp包含在2个不同的源文件中,那么该类将被双重定义。
包含该类的每个.cpp都可以很好地编译到目标文件中。但是,每个类必须只有1个定义,否则您将无法将目标文件链接在一起。
答案 4 :(得分:1)
与其他语言导入方法形成对比的#include最重要的一点是#include COPIES 放置#include指令的文件的内容。因此,在同一文件中声明和定义类将创建三件事:
显着增加你的编译 次。
如果您的定义不是内联的
你会得到链接器错误,因为
编译器找到多个
对相同功能的定义
这会暴露实施 对用户而不仅仅是界面。
这就是为什么通常的做法是在单独的文件中定义大型类,在某些情况下,在一个文件中使用小实现(如智能指针)的小型类(也隐式内联方法)。
答案 5 :(得分:1)
@Bill
我认为重要的是要强调比尔的观点:
<。> .h文件或多或少是“公共”文档,以便在概念上理解你的类在某些方面是如何工作的 - 一个接口。请记住,源文件应该被认为是专有的。我记得通过读取头文件,在我早期的C / C ++时代学到了很多关于Unix如何工作的知识。还要记住,内联函数的复杂性应该只不过是访问者的注意它有多容易 弄清楚如何使用MyClass。 头文件很重要 目的:他们向人们展示如何使用 你的班级。
答案 6 :(得分:0)
在cpp文件中定义类的一个重要原因是它不需要公开,它只是一个辅助函数(比如一个函子)。有些人似乎害怕将完整的类放在cpp文件中,而这只是表明你只想在那里使用类的意图。
答案 7 :(得分:0)
文件通常是版本控制系统的原子 - 如果您将事物明智地划分到不同的文件中,那么开发人员团队就可以只检查他们每个人需要处理的部分。将所有内容放在一个文件中,你就不能这样做。