如果我在头文件中实现了一个类,会发生什么
What happens if I implement a class in the header file?
可能重复:
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文件吗?
所有方法都将是内联方法。你可能会在整个编译上浪费一些最短的时间,但这没关系。据我所知,唯一可能发生的问题是如果你有一个静态的非成本成员变量。然后你必须为它分配一个存储位置(如果你愿意,可以放置一个定义和初始值),大概在.cpp
中,否则你会得到关于多个定义的链接器错误。
我见过在CPP中只有main()
函数的仅标题的项目,但这是大量模板化的。
C++17的更新:自C++17以来,您可以在头文件中将静态非常数成员声明为inline
。这使得只使用头的库很容易实现,而不需要在内联函数中使用类似体操的静态变量。
类定义本身不会生成任何代码。它只是向类的用户展示它是如何布局的,这样他们就可以生成适当的代码来操作它
生成代码的是类的成员函数。当您在类定义中定义成员函数时,它会为该函数提供一个隐式inline
声明。
函数调用可以通过以下两种方式之一进行编译和链接:
(1) 可以将末尾带有RETURN汇编指令的函数代码的单个副本放置在映像中,并且可以将CALL汇编指令(以及参数传递和返回值传递)放置在调用站点,以将控制权传递到此代码。
或
(2) 函数实现的整个副本可以替换调用站点上的整个函数调用。
声明为inline
的函数建议编译器使用第二种方法。此外,inline
声明允许在几个翻译单元中定义函数(因此可以将其放置在共享头文件中)。为了让编译器可以选择实现第二种方法,它需要在编译时复制函数实现。如果函数实现在外国翻译单元中,则此选项不可用。
还应该注意的是,现代编译器使用内联声明的函数来处理复杂的事情。参见:
http://gcc.gnu.org/onlinedocs/gcc/Inline.html
当在头文件中实现成员函数时,所有这些函数都隐式地成为inline
。
这意味着什么?它有什么含义
根据,C++03标准§7.1.3/4:
- 它提示编译器,在调用点替换函数体比通常的函数调用机制更可取
- 即使省略了内联替换,也要遵循内联的其他规则(尤其是w.r.t One Definition Rule)
因此,是的,每个翻译单元都有inline
函数的定义。这可能会导致二进制文件的大小增加。
通常,如果需要,任何优秀的主流编译器都会在调用时替换函数体,因此仅将函数inline
标记为#1并不是一个好主意,但如果您想让类的用户清楚地了解意图,则可以通过在头中定义函数或显式地将函数标记为inline
来实现。
我应该将示例拆分为
.h
和.cpp
文件吗
是的,这是大多数项目使用的常见编译模型,其中将接口(.h)与实现(.cpp)分离。这些接口作为头文件与代码的用户共享,而实现是以二进制文件的形式提供的。在某种程度上,这为您的知识产权提供了保障
这被称为分离模型。
使用模板的C++项目通常会使用包含模型,而不是通常C++项目的分离模型。
- C++从另一个类访问公共静态向量的正确方法是什么
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在另一个类视图中添加最多2个图表的正确方法是什么
- 当我们从/tp地址中添加/减去一个整数时会发生什么
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 将指针分配给另一个指针时会发生什么情况?
- 给定一个整数数组,需要在Max_Heap上运行操作。得到错误"segmentation fault",有什么想法吗?(C++)
- 我正在尝试制作一个程序,在添加 n 天(整数)后告诉一个人什么是一天(例如星期一等)
- 将一个双倍值乘以10会发生什么
- 什么 /可以/ 你从一个函数返回. 并期望它在到达时还活着?
- 如果我向一个12字节的缓冲区写入的字节数少于12,会发生什么情况
- 当一行中只有一个"#"而没有其他内容时,C++预处理器会做什么?
- 如何声明一个标准::提升直方图的向量?提升直方图的类型是什么?
- 当我尝试在函数内声明一个函数时,它不起作用?有什么建议吗?*源代码如下*
- 将(临时的?)std::string传递给使用它来构造一个接受副本的对象的函数的最佳方法是什么?
- 使用只有一个成员的工会的目的是什么?
- 将vector<vector<double>>从x86平台中创建的一个进程发送到x64中构建的另一个进程的最快方法是什么
- 除了调用全局删除运算符之外,删除一个void指针还能做什么呢
- 一个什么都不做的函数可以改变一个对象吗?