头文件基本上是预先编写的类吗? C ++

时间:2014-04-08 06:04:57

标签: c++ class directory header-files

正如它在标题中所述,是使用#include的头文件,基本上是预先编写的/预编码的类,其中包含方法和变量,一旦将其包含在脚本中,就可以使用它们。另外,如何才能使用您为自己的利益创建的头文件?一个简单的解释就可以了。

3 个答案:

答案 0 :(得分:2)

是和否......这取决于很多事情。

标准C ++的include指令-as可以是两件事:

#inlclude "filename"

#include <header>

第一个字面意思是“将文本保存在”文件名“中并将其粘贴到这里。 所以是的,文件可以包含预先编写的类(但不一定非必须)

第二个意思是“让这个源使用标准在其<header>部分中定义的设施。根据标准定义,这并不一定意味着是一个文件,尽管所有实现我都是我今天意识到这一点: header 是一个文件名,而<>""只是改变了编译器的搜索顺序。

你可以 - 在这一点上 - 将一个“非常长的Cpp源”剪切成较小的自包含块并转到一个cpp文件,该文件只不过是#includemain()的序列

但这不是全部。

C ++程序不一定由单个cpp文件构成(cpp文件加上它直接或间接包含的所有内容称为“翻译单元”)。

实际上编译不会产生程序,而是“目标文件”(术语是“古代操作系统术语”,与“面向对象编程无关”)是“链接器”组合在一起的。

因为调用另一个的C ++函数不需要 - 被翻译 - 知道另一个函数是如何被翻译的,而只是如何传递和获取其参数和返回值,这使你能够编写另一个函数body在另一个独立编译的源中,让header只包含它的声明(不是定义)。

例如,您可以

// fooclass.h
#ifndef FOOCLASS_H
#define FOOCLASS_H
class foo
{
public:
   void hello();
   void bye();
};
#endif // FOOCLASS_H

// out.h
#ifndef OUT_H
#define OUT_H 
#include <string>
void printout(const std::string& s);
#endif // OUT_H

//main.cpp
#include "fooclass.h"
int main()
{
   foo afoo;
   afoo.hello();
   afoo.bye();
}

// fooclass.cpp
#include "fooclass.h"
#include "out.h"

void foo::hello()
{ printout("hello"); }

void foo::bye()
{ printout("bye"); }

// out.cpp
#include "out.h"
#include <iostream>

void printout(const std::string& s)
{ std::cout << "- " << s << " -" << std::endl; }

整个程序可以编译(例如使用GCC)

g++ main.cpp fooclass.cpp out.cpp

或分开的步骤

g++ -c main.cpp
g++ -c fooclass.cpp
g++ -c out.cpp
g++ main.o fooclass.o out.o

(如果你使用MS编译器,你很可能会这样做

cl /c main.cpp
cl /c fooclass.cpp
cl /c out.cpp
link main.obj fooclass.obj out.obj

只有最后一步构成程序(注意main.cpp永远不会知道printout函数!)。前三个仅对已更改的文件是必需的,因此大型项目可以加快编译并将任务分配给不同的团队。 (像make这样的优点允许自动化这个东西。

所有这一切都有例外,现在越来越重要了:模板。 由于它们不是作为“要翻译的代码”而是作为“要扩展的代码”实现的,因此只有在知道它们必须扩展的内容时才能对它们进行翻译。

template<class T>
T max(const T& a, const T& b)
{ return (a<b)? b: a; }

(a<b)的含义取决于T类型实际上是什么。由于仅在调用max时才知道,因此最大值可以扩展为max<int>max<double>max<string> 只有在使用时。

出于这个原因,模板通常不在独立的翻译单元中处理,库提供模板类或函数通过提供包含所有代码的标题集合来完成,没有可单独编译的源。

答案 1 :(得分:0)

  

是使用#include的头文件,基本上是预先编写的/预编码的类,这些类填充了一些方法和变量,一旦将它们包含在脚本中就可以使用它?

这是一般概念。在C ++中,并不是所有东西都需要在一个类中,所以也可以有非成员函数,类型,预处理器定义,变量等。此外,一些标题声明变量,类型和/或函数但不定义它们 - 这意味着您可以限制使用它们,并且通常必须提供匹配的实现对象在链接或运行时。

  

另外,如何才能使用您为自己的利益创建的头文件?

关于它没有特别的魔力(尽管上面有关于上面的问题以了解你是否将实现置于行外),但首先只是在文件中抛出一些代码:< / p>

#pragma once
...

...然后#include来自另一个文件。如果包含文件在目录&#34; X&#34;中,那么您可以在目录&#34; X&#34;中包含标题。使用例如#include "the_header.h" - 使用双引号头文件名 - 即使未将编译器指定为包含目录作为命令行参数。

如果您的标题中有某些内容已声明但未定义,那么您将需要一个匹配的.cc / .cpp文件及其定义,您应将其编译成一个对象并使用该代码链接到该代码。图书馆。例如:

mylib.h
    #pragma one
    int fn();  // declared but not defined

mylib.cc
    #include "mylib.h"
    int fn() { return 42; }   // matching definition

cc -c mylib      // compile mylib.o

app.cc
    #include "mylib.h"
    int main()
    {
        return fn();
    }

cc -o app mylib.o

答案 2 :(得分:0)

c ++中头文件的常见用法是定义方法或类而不必实现它们。它定义了一个界面,或告诉你程序的其他部分如何与它们进行交互。它允许执行包含的文件知道他们需要知道的关于这些类/方法的内容,而不会告诉他们不需要的所有内容。在方法的情况下,您知道有一个方法doSomethingCool,并且您知道如何与它进行交互。只要您知道 ,您通常只需#include任何头文件doSomethingCool 定义,然后链接器在编译时发挥其魔力并找到您调用doSomethingCool的位置和“挂钩”以便与实际的实现代码对话,你可以在doSomethingCool.cpp中写一下。

使用函数,类和变量。