我一直在阅读有关Header文件的不同文章和教程。 我理解Headers服务的目的是保持实现的“接口”。 (以及其他类似的编译优化)
我仍然没有得到,并且真的无法解开它,你总是使用标题吗? 我知道你可以在头文件本身中编写代码块。但那是我迷路的地方。
当我查看视频教程时,人们只需在Header文件中定义函数。然后另一篇文章只定义了函数(我猜这是接口的想法)。
目前我正在创建一个名为Color的简单类。 实现:
/*
* File: Color.cpp
* Author: Sidar
*
* Created on 26 december 2011, 16:02
*/
#include <stdio.h>
#include "Color.h"
Color::Color() {
reset();
}
Color::Color(const Color& orig) {
a = orig.a;
r = orig.r;
g = orig.g;
b = orig.b;
}
void Color::reset()
{
a = 0;
r = 0;
g = 0;
b = 0;
}
Color::Color(unsigned int r, unsigned int g, unsigned int b, unsigned int a)
{
this->r = r;
this->g = g;
this->b = b;
this->a = a;
}
Color::~Color() {
r = 0;
g = 0;
b = 0;
}
//getters____________________________
unsigned int Color::getRed() const
{
return r;
}
unsigned int Color::getBlue() const
{
return b;
}
unsigned int Color::getGreen() const
{
return g;
}
unsigned int Color::getAlpha() const
{
return a;
}
//setters____________________________
void Color::setRed(unsigned int r)
{
if(r > 255)r = 255;
if(r < 0)r = 0;
this->r = r;
}
void Color::setGreen(unsigned int g)
{
if(g > 255)g = 255;
if(g < 0)g = 0;
this->g = g;
}
void Color::setBlue(unsigned int b)
{
if(b > 255)b = 255;
if(b < 0)b = 0;
this->b = b;
}
void Color::setAlpha(unsigned int a)
{
if(a > 255)a = 255;
if(a < 0)a = 0;
this->a = a;
}
unsigned int Color::color()
{
return (int)a << 24 | (int)r << 16 | (int)g << 8 | (int)b << 0;
}
这里是标题
/*
* File: Color.h
* Author: Sidar
*
* Created on 26 december 2011, 16:02
*/
#ifndef COLOR_H
#define COLOR_H
#include <string>
class Color {
public:
Color();
Color(const Color& orig);
Color(unsigned int r,unsigned int g,unsigned int b, unsigned int a);
virtual ~Color();
//____________________
void setRed(unsigned int r);
unsigned int getRed()const;
//____________________
void setBlue(unsigned int b);
unsigned int getBlue()const;
//____________________
void setGreen(unsigned int g);
unsigned int getGreen()const;
//____________________
void setAlpha(unsigned int a);
unsigned int getAlpha()const;
//____________________
unsigned int color();
void reset();
private:
unsigned int r;
unsigned int b;
unsigned int g;
unsigned int a;
};
#endif /* COLOR_H */
此代码确实有效,我没有收到任何错误。但这是header和cpp文件的一般概念吗? 我的第二个问题: 我读了很多,当使用模板时,我更容易在Header中实现代码我理解这一点(以防止许多实现被认为是如此通用的东西)。但是还有其他情况吗?
答案 0 :(得分:4)
您并非“总是”做任何事情,这完全取决于您的团队或组织的环境,目标和编码标准。
C ++是一种非常灵活的语言,允许以多种不同的方式完成和组织事物。
可能会使用单独的实施文件:
将实现与界面分开,就像你一样 建议
加快编译时间
处理循环依赖
因此,您可以发送仅包含头文件的二进制库,而不是 基础源代码
您可能不需要单独的实施文件的一些原因:
您使用模板,“通常”必须使用模板定义 声明
您不希望将实现与接口分开。在 在许多情况下,这使得事情更容易理解,因为你没有 在标头和实现文件之间来回切换。这个 如果你正在处理大班,可能会适得其反 但是很多方法。
您希望尽可能多的代码由编译器内联 可能的。
您正在创建一个您不想要用户的代码库 不得不担心建设。大多数Boost库都是 这样,你就不必使用Boost构建系统了 可能是一件苦差事,但你只需要包含头文件 在你的代码中,你需要做的就是使用它们。
我通常通过定义头文件中的所有逻辑来开始新类的工作。然后当类完成时,或者当它开始变得拥挤在头文件中时,我将开始将逻辑移到单独的实现文件中。这完全是为了充分利用我的时间,因为当我可以在同一个文件中看到所有内容时,我能够更快地完成工作并减少错误。
还应该注意,您根本不必使用头文件。您可以直接在.cpp文件中定义一些类。这通常是针对永远不会在.cpp文件之外使用的私有类完成的。
答案 1 :(得分:0)
好的,首先,这里是为什么模板只能在头文件中实现的答案:
Why can templates only be implemented in the header file?
这不是因为它是通用的,而是因为编译器实际处理模板的方式。如果你没有得到解释,请告诉我:)。
答案 2 :(得分:0)
如果将方法实现放在头文件中,C ++编译器可能会选择在调用站点内联代码。所以它可以更有效率。
如果你在一个头文件中完全定义了一个类,那么你就不需要一个.cpp文件来制作东西(如果实现很简单),那就更容易理解了。
答案 3 :(得分:0)
头文件不用于将“接口”与实现“分离”,它们已包含许多实现细节,除非您使用pimpl习惯用法。那是一个不同的主题,它可以用任何没有C#和Java等“头”文件的语言来完成。
它们的真正用途来自这样一个事实:当编译器必须为类的实例分配空间时,它必须知道它的大小。要计算大小,它需要该类的完整声明。由于您可能会在许多翻译单元中使用该类的实例,因此提供该声明的唯一理智方法是将其放在头文件中并在需要时#include它。
当您创建指向实例(或引用)的指针时,编译器不需要知道该类的大小,因为指针通常具有相同的4或8字节大小。对于这些情况,您可以使用前向声明而不是#including标头。
现在,您可以在头文件中包含代码的原因是由于当前的C ++模板机制。该代码将被编译多次,但编译器/链接器将消除所有副本并在最终编译的代码中保留一个副本。