在C ++中使用不带合作伙伴Class/Cpp文件的标头文件是否可行 [英] Is it practical to use Header files without a partner Class/Cpp file in C++

查看:52
本文介绍了在C ++中使用不带合作伙伴Class/Cpp文件的标头文件是否可行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近学习了C ++,这是我的课程的一部分,我试图更深入地了解标头和类之间的伙伴关系.在每一个示例或教程中,我都查看了头文件,它们都使用带有构造函数的类文件,然后继续使用方法(如果包含).但是,我想知道仅使用头文件来保存一组相关功能是否合适,而不必每次使用它们时都需要使该类成为对象.

 //主文件#include< iostream>#include"Example.h"#include"Example2.h"int main(){//示例1例子a;//我必须先创建一个类的对象a.square(4);//然后我可以调用该函数//示例2正方形(4);//我可以在不需要构造函数的情况下调用该函数std :: cin.get();} 

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

 //Example1 cpp#include< iostream>#include"Example.h"无效的例子:: square(int i){我* =我;std :: cout<<我<<std :: endl;}//Example1标头类示例{上市:空方(int i);}; 

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

 //Example2标头空方(int i){我* =我;std :: cout<<一世;} 

最终,我想我要问的是,仅使用头文件来容纳一组相关功能而不创建相关类文件是否可行.如果答案是否定的,那么背后的原因是什么.无论哪种方式,我都确定我已经看过了一些东西,但是一如既往,我感谢你们对此提供的任何见识!

解决方案

当然,只包含标头就可以了(只要您已经考虑了前面提到的一个定义规则"即可).

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

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

我做了以下人为设计的反例:

main.cc :

  #include< iostream>//定义浮点数float aFloat = 123.0;//设为外部extern float aFloat;/*这应该包含在标题中*但是我阻止了预处理器的使用*并自己完成.*/extern void printADouble();int main(){std :: cout<<"printADouble():";printADouble();std :: cout<<"\ n""Surprised?:-)\ n";返回0;} 

printADouble.cc :

 /*这应该包含在标题中*但是我阻止了预处理器的使用*并自己完成.**这是故意的错误类型*(以显示错误的处理方式).*///使用extern aFloatextern double aFloat;//设为外部extern void printADouble();无效printADouble(){std :: cout<<浮动;} 

希望您注意到我宣布了

  • extern float aFloat main.cc
  • printADouble.cc 中的
  • extern double aFloat

那是一场灾难.

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

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

将这些混乱链接在一起时出现问题吗?否.链接器可以解析所有需要的符号.

输出:

  printADouble():5.55042e-315感到惊讶吗?:-) 

符合预期(假设您以及我都没有任何理智的认识).

在魔盒上进行实时演示

printADouble()访问定义的 float 变量(4个字节)作为 double 变量(8个字节).这是未定义的行为,并且在多个级别上都出错.

因此,使用标头不支持,但可以启用C ++中的(某种)模块化编程.(直到我曾经不得不使用还没有预处理器的C编译器之前,我才意识到差异.因此,以上概述的问题对我造成了很大的打击,但对我来说也确实很有启发性.)/p>

恕我直言,头文件是对模块化编程的基本功能(即,接口的明确定义以及接口和实现的分离,作为语言功能)的实用替代.这似乎也使其他人感到烦恼.看看有关C ++模块的一些话明白我的意思.

I've recently picked up C++ as part of my course, and I'm trying to understand in more depth the partnership between headers and classes. From every example or tutorial I've looked up on header files, they all use a class file with a constructor and then follow up with methods if they were included. However I'm wondering if it's fine just using header files to hold a group of related functions without the need to make an object of the class every time you want to use them.

//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();
}

In the first example I create an object and then call the function, i use the two files 'Example.h' and '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);
};

In example2 I call the function directly from file 'Example2.h' below

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

Ultimately I guess what I'm asking is, if it's practical to use just the header file to hold a group of related functions without creating a related class file. And if the answer is no, what's the reason behind that. Either way I'm sure I've over looked something, but as ever I appreciate any kind of insight from you guys on this!

解决方案

Of course, it's just fine to have only headers (as long as you consider the One Definition Rule as already mentioned).

You can as well write C++ sources without any header files.

Strictly speaking, headers are nothing else than filed pieces of source code which might be #included (i.e. pasted) into multiple C++ source files (i.e. translation units). Remembering this basic fact was sometimes quite helpful for me.

I made the following contrived counter-example:

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;
}

Hopefully, you have noticed that I declared

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

which is a disaster.

Problem when compiling main.cc? No. The translation unit is consistent syntactically and semantically (for the compiler).

Problem when compiling printADouble.cc? No. The translation unit is consistent syntactically and semantically (for the compiler).

Problem when linking this mess together? No. Linker can resolve every needed symbol.

Output:

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

as expected (assuming you expected as well as me nothing with sense).

Live Demo on wandbox

printADouble() accessed the defined float variable (4 bytes) as double variable (8 bytes). This is undefined behavior and goes wrong on multiple levels.

So, using headers doesn't support but enables (some kind of) modular programming in C++. (I didn't recognize the difference until I once had to use a C compiler which did not (yet) have a pre-processor. So, this above sketched issue hit me very hard but was really enlightening for me, also.)

IMHO, header files are a pragmatic replacement for an essential feature of modular programming (i.e. the explicit definion of interfaces and separation of interfaces and implementations as language feature). This seems to have annoyed other people as well. Have a look at A Few Words on C++ Modules to see what I mean.

这篇关于在C ++中使用不带合作伙伴Class/Cpp文件的标头文件是否可行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆