C ++的常见做法是将.h
(或.hpp
)中的声明和实现分隔为.cpp
。
我知道两个主要原因(也许还有其他原因):
编译速度(仅更改一个文件就不必重新编译所有文件,可以通过make
预编译的.o
文件进行链接)
前向声明有时是必需的(当执行class A
depends class B
和class B
on时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#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#include #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的工作方式。出于这个原因,我仅通过将所有代码(包括实现)放入内部来编写C ++程序.h
。像这样:
#includeclass 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
and .cpp
)组织程序结构,我觉得这更方便吗?
但是,现在当我开始编写更复杂的程序时,由于我必须一直重新编译所有内容,因此编译时间开始变得很长。
分离头文件和类文件的最佳点之一就是您不必编译所有内容。
当您具有class1.h,class1.cpp,class2.h,class2.cpp,...,classN.h和classN.cpp时,这些标头仅包含在每个类的已编译对象中。因此,如果函数的逻辑在class2中发生变化,但标头未发生变化,则只需将class2编译为目标文件。然后,将链接所有产生实际可执行文件的目标文件。链接是快速的。
如果要构建大型而复杂的程序,并发现编辑标题是问题,请在编写应用程序之前考虑对其进行设计。