对于C++中头文件的实际用途感到困惑

9 浏览
0 Comments

对于C++中头文件的实际用途感到困惑

我对C++的头文件有些困惑,原因如下:

  1. 我原以为头文件的目的是将接口和实现分离。换句话说,客户端使用头文件来学习如何使用类,但不必关心类如何在内部实现这个功能。
  2. 那么,为什么C++类的私有变量要在其头文件中指定?

在我看来,将私有变量放在头文件中违反了接口和实现的分离。直觉上,我认为将私有变量放在源文件中更有意义,因为源文件不会被外部世界所暴露。

也许我只是对头文件的目的有误解,上述的第一点完全错误了?有哪些方面是错误的?

0
0 Comments

C++中头文件的实际目的是为了给编译器提供必要的信息,以在编译单元(.cpp源文件)之间共享定义。这是一种机械性的事情,而不是一种哲学性的问题。

例如,私有成员变量需要被声明,因为它们定义了对象的大小,编译器在分配对象时需要知道大小。

难道正确的术语不应该是“在编译单元之间共享声明”吗?这经常让人困惑,关于声明和定义的含义是什么...

- makulik,我在使用“definitions”一词时是按照英语的意思,而不是正式的C++用法。而且在头文件中包含定义是完全可能的,例如使用模板几乎是必须的。

为什么只有私有成员变量?

- 不是只有私有成员变量,那只是一个例子。实际上需要的是整个声明。

谢谢Mark。实际上,我很惊讶没某些情况下分配(除了你),因为我相信这是C++需要将对象状态放在头文件中的主要原因,以便在栈上进行分配时知道它的大小。我猜当时这是他们能想到的唯一方式。尽管Java把所有东西都混在了一起,但它把问题搞得更糟了一点。

在C++中,头文件的主要目的是为了在编译单元之间共享定义。头文件包含了需要在多个源文件中共享的声明和定义。例如,私有成员变量的大小需要在对象分配时由编译器确定,因此必须在头文件中声明。这种机械性的操作确保了编译器在编译不同的源文件时能够正确地处理对象的定义和分配。然而,有时关于声明和定义的术语的混淆会导致困惑。此外,头文件还可以包含模板定义等,以满足特定的编程需求。头文件在C++中起到了重要的作用,确保了代码的正确性和可维护性。

0
0 Comments

在C++中,函数和类的声明和定义是有区别的。一般来说,C++的头文件包含了一个类的声明。由于不允许有部分声明,头文件需要包含完整的类声明,包括所有私有成员(变量和成员函数)。

如果你想将完整的实现从公共部分隐藏起来,可以使用pimpl idiom来实现。

解决方法:

- 将类的声明放在头文件中,包括所有私有成员。

- 将类的定义放在源文件中,只在需要的时候包含头文件。

- 使用pimpl idiom来隐藏完整的实现,将实现细节放在源文件中的一个私有类中。

以下是一个示例:

// MyClass.h 头文件
class MyClass
{
public:
    MyClass();
    void doSomething();
private:
    int privateVar;
    void privateFunction();
};
// MyClass.cpp 源文件
#include "MyClass.h"
class MyClassImpl
{
public:
    void privateFunction()
    {
        // 实现细节
    }
};
MyClass::MyClass() : privateVar(0)
{
    // 构造函数实现
}
void MyClass::doSomething()
{
    // 公共函数实现
    MyClassImpl impl;
    impl.privateFunction();
}

通过将类的定义放在源文件中,并使用pimpl idiom来隐藏私有函数的实现细节,可以避免将完整的实现暴露给公共部分。这样可以提高代码的封装性和可维护性。

0
0 Comments

C++语言中,头文件的主要功能是为了弥补其他语言中的模块导入或类似功能的缺失。编译器只能通过使用#include将其他文件的代码粘贴到当前源文件中,以了解类型、函数等信息。

理论上,你也可以将所有的源代码都放在头文件中,然后只有一个源文件包含所有的头文件。之所以通常不这样做,有两个原因。首先,这样编译时间会更长(对于一些项目来说是一个重要的问题),并且任何文件的任何更改都会导致整个项目的重新编译。其次,将实现放在源文件中实际上有助于将接口与实现分离,即使部分实现仍然在头文件中指定。

需要注意的是,在头文件中内联方法也需要在公共/客户端代码中公开的实现细节之间取得平衡。

如果你真的希望完全将接口与实现分离(这确实有一定的优点),C++的做法是利用pimpl模式。使用这种模式,所有的私有数据都被隐藏在源文件中,只提供一个抽象接口给公共代码。此外,使用非虚接口(NVI)模式可以进一步帮助隔离客户端代码与接口的变化。

C++头文件的实际目的在于通过#include指令将其他文件的代码粘贴到当前源文件中,以便编译器了解类型、函数等信息。同时,将实现放在源文件中有助于将接口与实现分离,而使用pimpl模式和NVI模式可以进一步提高代码的隔离性。

0