如果我在头文件中实现一个类会怎么样?

时间:2012-09-04 09:12:27

标签: c++ header

  

可能重复:
  Inline functions in C++

如果我在其头文件中完全实现一个类,编译器会做什么?一个典型的例子如下:

class MyException
{    
public:
    explicit MyException(const char* file, int line) file(file), line(line) {};
    const char* getFile() const { return file };
    int getLine() const { return line };
private:
    const char* const file;
    const int line;
};

我的目的是使用这样的课程:throw MyException(__FILE__, __LINE__)

我将此头文件包含在每个.cpp文件中。我想编译器将按照定义的次数编译该类,并将(相同的)机器代码包含在它生成的每个目标文件中。现在,链接器会做什么?我尝试了一个更简单的例子(没有所有那些讨厌的const)并且编译得很好。

如果不是简单的类,我在头文件中实现了一个三屏长的C函数会发生什么?最后一个问题,我应该将我的例子分成.h和.cpp文件吗?

3 个答案:

答案 0 :(得分:3)

类定义本身不会产生任何代码。它只是向类的用户显示它是如何布局的,因此他们可以生成适当的代码来操作它。

这是生成代码的类的成员函数。在类定义中定义成员函数时,它为函数提供隐式inline声明。

可以通过以下两种方式之一编译和链接函数调用:

(1)可以在图像中放置一个带有RETURN汇编指令的功能代码的单个副本,并且可以在呼叫站点放置CALL汇编指令(以及param传递和返回值传输)将控制转移到此代码。

(2)函数实现的整个副本可以替换调用站点上的整个函数调用。

声明为inline的函数是建议编译器以第二种方式执行此操作。此外,inline声明允许在多个转换单元中定义函数(因此可以将其放在共享头文件中)。为了使编译器可以选择实现第二种方法,它需要在编译时获得函数实现的副本。如果函数实现位于外部翻译单元中,则不可用。

还应该注意的是,现代编译器使用内联声明的函数来做复杂的事情。参见:

http://gcc.gnu.org/onlinedocs/gcc/Inline.html

答案 1 :(得分:3)

所有方法都是内联方法。你可能会在整个编译过程中失去一些时间,但没关系。据我所知,知道唯一可能出现的问题是你有一个静态的非成本成员变量。然后你必须为它分配一个存储位置(如果你想要的话,放置一个定义和初始值),大概是.cpp,否则你会得到关于多重定义的链接器错误。

我见过只有标题的项目,它们在CPP中只有main()函数,但这是很模糊的。

答案 2 :(得分:3)

在头文件中实现成员函数时,所有这些函数都隐式inline

  

这意味着什么?它有什么含义?

按照, C ++ 03标准§7.1.3/ 4:

  • 它提示编译器在调用点处替换函数体优于通常的函数调用机制。
  • 即使省略内联替换,也会遵循内联的其他规则(特别是w.r.t One Definition Rule)。

是的,每个翻译单元都会定义inline函数。这个可能会导致二进制文件的大小增加。

通常任何好的主流编译器都会在需要时在调用点替换函数体,因此仅为#1标记函数inline并不是一个好主意,但是如果你想让你的 意图 向您的班级用户清楚,然后您可以通过在标题中定义函数或明确将您的函数标记为inline来实现。

  

我应该将我的示例拆分为.h.cpp个文件吗?

是的,这是大多数项目使用的常用编译模型,其中您将接口(.h)与实现(.cpp)分开。接口与代码用户共享为头文件,而实施以二进制文件的形式提供。若某些范围,这为您的知识产权提供了保障。
这称为 分离模型

使用模板的C ++项目通常使用 包含模型 ,而不是通常的C ++项目的分离模型。