[英](avoid) splitting code to .cpp and .h in C++ and efficient compilation
C ++中的常见做法是将.h
(或.hpp
)和实现中的声明分隔为.cpp
。
我知道两个主要原因(也许还有其他原因):
.o
文件中的make
链接它) class A
class B
实现依赖于class B
和class A
class B
class A
)......但我没有经常这样的问题而且我可以解决它。 在面向对象编程的情况下,它看起来像这样:
QuadraticFunction.h
:
class QuadraticFunc{
public:
double a,b,c;
double eval ( double x );
double solve( double y, double &x1, double &x2 );
};
QuadraticFunction.cpp
:
#include <math.h>
#include "QuadraticFunc.h"
double QuadraticFunc::eval ( double x ){ return c + x * (b + x * a ); };
double QuadraticFunc::solve( double y, double &x1, double &x2 ){
double c_ = c - y;
double D2 = b * b - 4 * a * c_;
if( D2 > 0 ){
double D = sqrt( D2 );
double frac = 0.5/a;
x1 = (-b-D)*frac;
x2 = (-b+D)*frac;
}else{ x1 = NAN; x2 = NAN; }
};
main.cpp
:
#include <math.h>
#include <stdio.h>
#include "QuadraticFunc.h"
QuadraticFunc * myFunc;
int main( int argc, char* args[] ){
myFunc = new QuadraticFunc();
myFunc->a = 1.0d; myFunc->b = -1.0d; myFunc->c = -1.0d;
double x1,x2;
myFunc->solve( 10.0d, x1, x2 );
printf( "soulution %20.10f %20.10f \n", x1, x2 );
double y1,y2;
y1 = myFunc->eval( x1 );
y2 = myFunc->eval( x2 );
printf( "check %20.10f %20.10f \n", y1, y2 );
delete myFunc;
}
然后用makefile
编译它,如下所示:
FLAGS = -std=c++11 -Og -g -w
SRCS = QuadraticFunc.cpp main.cpp
OBJS = $(subst .cpp,.o,$(SRCS))
all: $(OBJS)
g++ $(OBJS) $(LFLAGS) -o program.x
main.o: main.cpp QuadraticFunc.h
g++ $(LFLAGS) -c main.cpp
QuadraticFunc.o: QuadraticFunc.cpp QuadraticFunc.h
g++ $(LFLAGS) -c QuadraticFunc.cpp
clean:
rm -f *.o *.x
但是,我发现它经常非常不方便
特别是,当您更改代码时(例如,在您尚未确定整个项目的整体结构时,在开发的初始阶段)。
.cpp
和.h
部分代码之间来回切换。 QuadraticFunc::
:),你可以做很多拼写错误和不一致的事情,所以编译器会一直抱怨(我经常犯这样的错误) Makefile
,在那里你会做很多其他错误,这些错误很难从编译器输出中跟踪(例如,我经常忘记编写Makefile,以便代码重新编译每个依赖项,我编辑) 从这个角度来看,我更喜欢Java的工作原理。 出于这个原因,我只是通过将所有代码(包括实现)放在.h
编写我的C ++程序。 像这样:
#include <math.h>
class QuadraticFunc{
public:
double a,b,c;
double eval ( double x ){ return c + x * (b + x * a ); }
double solve( double y, double &x1, double &x2 ){
double c_ = c - y;
double D2 = b * b - 4 * a * c_;
if( D2 > 0 ){
double D = sqrt( D2 );
double frac = 0.5/a;
x1 = (-b-D)*frac;
x2 = (-b+D)*frac;
}else{ x1 = NAN; x2 = NAN; }
};
};
使用通用默认的makefile,如下所示:
FLAGS = -std=c++11 -Og -g -w
all : $(OBJS)
g++ main.cpp $(LFLAGS) -w -o program.x
( main.cpp
保持不变)
但是,现在当我开始编写更复杂的程序时,编译时间开始很长,因为我必须一直重新编译所有内容。
有没有办法如何利用make
优点 (更快的编译时间) ,仍然以类似Java的方式组织程序结构 (类体中的所有内容而不是单独的.h
和.cpp
)我觉得更方便吗?
但是,现在当我开始编写更复杂的程序时,编译时间开始很长,因为我必须一直重新编译所有内容。
分隔标题和类文件的最佳点之一是您不必编译所有内容。
当你有class1.h,class1.cpp,class2.h,class2.cpp,...,classN.h和classN.cpp时,这些头只包含在每个类的编译对象中。 因此,如果你的函数的逻辑在class2中发生了变化但你的标题没有,那么你只需要将class2编译成目标文件。 那么你会做产生的实际的可执行所有目标文件的链接 。 链接很快。
如果您正在构建大型复杂程序并发现编辑标题是问题,请在编写之前考虑设计您的应用程序。
简答:不。
答案很长:仍然没有。
您可以将所有代码放在头文件中,也可以使用两个文件,其中包含标头,源文件自行编译。
我个人对使用两个文件没有任何问题。 大多数编辑器支持“双文件视图” - 其中大多数也支持“跳转到定义”。
将所有函数放在类声明中也有另一个副作用,即所有函数都标记为内联,这可能导致在输出二进制文件中多次生成函数(如果多个源文件中包含相同的标头)。
虽然编译时间,根据我的经验,不是解析的结果,而是编译的代码生成部分 - 通常是.cpp文件 - 所以如果你包含几个大标题,那么很可能不会那么重要。
当然使用make
[或类似的]与正确定义的依赖项来构建项目。
C ++是C ++,Java是Java。 在.h- und .cpp文件中拆分源代码是C ++语言概念的一部分。 如果你不喜欢它,你不应该使用它。
将所有内容放在一个头文件中与包含.cpp文件(可行但非常不合适)的实际相同。 你不应该这样做:
例子:WindowsAPI的(COM !!),SFML,升压(部分)(以及更多 )
你可以这样做:
示例:提升(部分)
你必须这样做:
示例: STL(C ++标准模板库)
首先,由于可重复性,您必须在分离的文件中编写实现和定义。 有可能将它们放入同一个文件中,但它不可读。 编写代码时,请为需要理解代码的下一个贡献者编写代码。 这很重要,因为下一个可能是你:)第二个问题是makefile。 Make是为了简化编译过程而不是更快。 因此,如果您在任何文件中进行更改,则无需更改ant make文件。 感谢make,你不需要一次又一次地编译你的文件。写一次文件,每次都使用。 但是如果添加影响编译过程的新代码文件,是的,你必须在makefile中进行更改。 您可以在google c ++样式指南中了解有关可读性,编写定义和实现的更多信息以及所有其他样式问题以及gnu make manuel中的makefile。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.