我有一个理论问题而不是错误报告。
我是一名新手C ++程序员,试图将其推广
使用VC ++ VS2008编译器
我经常发现自己想知道为什么我要在头文件中采取一些行动。
例如,请查看此代码块:
#include "DrawScene.h"
#include "Camera.h"
#include "Player.h"
#include "Grid.h"
#include "InputHandler.h"
#include "GameState.h"
class Controller
{
public:
private:
public:
Controller();
~Controller(){}
void Update();
private:
};
连接的CPP文件,controller.cpp及其
#include "stdafx.h"
#include "glut.h"
#include "Controller.h"
#include <iostream>
Grid* grid_ptr = new Grid();
InputHandler* inputHandler_ptr = new InputHandler();
DrawScene* drawScene_ptr = new DrawScene();
GameState* gameState_ptr = new GameState();
Controller::Controller()
{
}
void Controller::Update()
{
}
决定哪些包括去哪里的好方法是什么?到目前为止,我一直在使用“无论如何工作”的方法,但我发现它有点不专业。
现在即使您可以说我的代码有X语法错误和设计缺陷,但请注意,我很欣赏有关使用.h VS .cpp文件的信息。
为什么还有这样的设计呢?在制作任何基于OOP的C ++程序时,总是会轻易踩着什么坑和陷阱?
是什么引发了这个问题,顺便说一下,我想通知读者头文件中存在控制器中存在的对象,但是如果不将它们设置为静态,则分配这些未初始化的对象似乎是不可能的。
注意:我来自C# - &gt; C ++,可能有助于了解。这就是我对代码的看法。
提前感谢您的努力!
编辑:26/08/2010 18:16
所以构建时间是好包含的本质。还有更多需要谨慎吗?
答案 0 :(得分:15)
这是我个人的意见,而不是一致的最佳做法,但我建议的是:在头文件中,只包含使头文件的内容编译所必需的那些头文件语法错误。如果您可以使用前向声明而不是嵌套包含,请执行此操作。
原因是,在C ++中(与C#不同,iiuc)没有出口控制。您在标题中包含的所有内容都将显示在标题的包含者中,这可能是您的界面用户看不到的大量垃圾。
答案 1 :(得分:4)
如果绝对必要,只在其他标头中包含标头。如果标题只能在源文件中,那么这是最好的地方。如果您只使用指针和对它们的引用,则可以在标头中使用类的前向声明。您的DrawScene
,GameState
,Grid
和InputHandler
类看起来可能属于此类。
请注意,C ++作为一种语言并不关心标头和源文件之间的区别。这只是开发人员用来维护代码的极其常见的系统。使用标头的明显优势是避免代码重复,并在一定程度上有助于为类,模板和内联函数强制执行单定义规则。
答案 2 :(得分:4)
一般来说,标题应该驻留在cpp文件中。对于标准库包括(可能包括第3个库),您可以将它们粘贴在标题中。但是,为您的项目专门定义的标头应尽可能使用cpp文件。
原因是编译时间和依赖性问题。每次更改头文件时,编译器都必须重新编译包含它的每个源文件。当您在另一个头文件中包含头文件时,编译器必须重新编译包含头文件的每个cpp文件。
这就是前向声明和PIMPL(指向IMPLementation或不透明指针)模式很受欢迎的原因。它允许您将至少一些更改/实现从头文件中移出。例如:
// header file:
class SomeType;
class AnotherType
{
private:
SomeType *m_pimpl;
};
不要求你包含“sometype.h”而是:
// header file
class AnotherType
{
private:
SomeType m_impl;
};
一样。编辑:实际上,如果你总是在包含“anothertype.h”的每个cpp文件中的“anothertype.h”之前包含“sometype.h”,则不需要在“anothertype.h”中包含“sometype.h”。
有时将头文件移动到cpp文件可能很困难。那时你有一个决定 - 最好是通过抽象代码来完成这样做,或者更好的方法是添加包含?
答案 3 :(得分:3)
避免在.h文件中放置太多(读取,任何不必要的)#includes
。这样做会导致构建时间过长,例如无论何时更改Camera.h,您都将更改Controller.h,因此需要重建包含Controller.h的任何内容。即使它只是一个已经改变的评论。
如果您只存储指针成员,则使用前向声明,然后将#includes
添加到cpp文件。
理论上,.h文件只包含接口和.cpp文件,实现。但是,由于私有成员可以说是实现,而不是接口,因此这不是严格正确的,因此需要前向声明以最大限度地减少不必要的重建。
在C ++中,可以将整个实现内联包含在类定义文件中,就像使用Java一样,但这确实打破了.h / .cpp接口/实现规则。
答案 4 :(得分:2)
头文件包含函数,类和其他对象的声明,而cpp文件用于实现这些先前声明的对象。
头文件主要由于历史原因而存在。如果在实际调用代码之前给出了代码使用的所有函数,类等的定义,那么构建C ++编译器会更容易。
通常您使用cpp进行实施。在头文件中实现函数会自动内联它们,因此除非它们非常小和/或经常被调用,否则通常不是你想要的。