在 C++ 中使用没有伙伴类/Cpp 文件的头文件是否实用

2023-12-05

我最近选择了 C++ 作为我课程的一部分,并且我试图更深入地了解标头和类之间的合作关系。从我查找过的头文件中的每个示例或教程中,它们都使用带有构造函数的类文件,然后跟进方法(如果包含它们)。但是我想知道是否可以只使用头文件来保存一组相关函数,而无需每次要使用它们时都创建该类的对象。

//main file
#include <iostream>
#include "Example.h"
#include "Example2.h"

int main()
{
    //Example 1
    Example a; //I have to create an object of the class first
    a.square(4); //Then I can call the function

    //Example 2
    square(4); //I can call the function without the need of a constructor

    std::cin.get();
}

在第一个示例中,我创建一个对象,然后调用该函数,我使用两个文件“Example.h”和“Example.cpp”

  //Example1 cpp
    #include <iostream>
    #include "Example.h"

void Example::square(int i)
{
    i *= i;
    std::cout << i << std::endl;
}
//Example1 header
class Example
{
public:
    void square(int i);
};

在 example2 中,我直接从下面的文件“Example2.h”调用该函数

//Example2 header
void square(int i)
{
    i *= i;
    std::cout << i;
}

最终我想我要问的是,仅使用头文件来保存一组相关函数而不创建相关类文件是否可行。如果答案是否定的,那么背后的原因是什么?不管怎样,我确信我已经忽略了一些东西,但我一如既往地感谢你们对此的任何见解!


当然,只有标题就可以了(只要您考虑已经提到的单一定义规则)。

您也可以编写没有任何头文件的 C++ 源代码。

严格来说,标头只不过是归档的源代码片段,可能是#included(即粘贴)到多个 C++ 源文件(即翻译单元)中。记住这个基本事实有时对我很有帮助。

我做了以下人为的反例:

main.cc:

#include <iostream>

// define float
float aFloat = 123.0;

// make it extern
extern float aFloat;

/* This should be include from a header
 * but instead I prevent the pre-processor usage
 * and simply do it by myself.
 */
extern void printADouble();

int main()
{
  std::cout << "printADouble(): ";
  printADouble();
  std::cout << "\n"
    "Surprised? :-)\n";
  return 0;
}

printADouble.cc:

/* This should be include from a header
 * but instead I prevent the pre-processor usage
 * and simply do it by myself.
 *
 * This is intentionally of wrong type
 * (to show how it can be done wrong).
 */

// use extern aFloat
extern double aFloat;

// make it extern
extern void printADouble();

void printADouble()
{
  std::cout << aFloat;
}

希望你已经注意到我声明了

  • extern float aFloat in main.cc
  • extern double aFloat in printADouble.cc

这是一场灾难。

编译时出现问题main.cc?不会。翻译单元在语法和语义上(对于编译器)是一致的。

编译时出现问题printADouble.cc?不会。翻译单元在语法和语义上(对于编译器)是一致的。

将这些乱七八糟的东西连接在一起时出现问题吗?不会。链接器可以解析每个需要的符号。

Output:

printADouble(): 5.55042e-315
Surprised? :-)

正如预期的那样(假设你和我都没有任何理智的预期)。

wandbox 上的现场演示

printADouble()访问了定义的float变量(4字节)为double变量(8 个字节)。这是未定义的行为,并且在多个层​​面上都会出错。

因此,使用标头不支持但支持 C++ 中的(某种)模块化编程。 (直到我曾经不得不使用还没有预处理器的 C 编译器时,我才意识到其中的区别。所以,上面概述的这个问题对我来说非常打击,但对我来说也确实很有启发。)

恕我直言,头文件是模块化编程基本功能的实用替代品(即接口的显式定义以及接口和实现作为语言功能的分离)。这似乎也惹恼了其他人。看一下关于 C++ 模块的几句话看看我的意思。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C++ 中使用没有伙伴类/Cpp 文件的头文件是否实用 的相关文章