Обычной практикой в C ++ является разделение объявлений в .h
(или .hpp
) и реализации в .cpp
.
Я знаю две основные причины (может быть, есть и другие):
- Скорость компиляции (вам не нужно перекомпилировать все, когда вы меняете только один файл, вы можете связать его
make
из предварительно скомпилированных.o
файлов) - Иногда необходимы предварительные объявления (когда реализация
class A
зависит отclass B
, а реализация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. По этой причине я писал свои программы на C ++, просто помещая весь код (включая реализацию) внутрь .h
. Нравится:
#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; }
};
};
с универсальным make-файлом по умолчанию, например:
FLAGS = -std=c++11 -Og -g -w
all : $(OBJS)
g++ main.cpp $(LFLAGS) -w -o program.x
(main.cpp
остается прежним)
Однако теперь когда я начинаю писать более сложные программы, время компиляции становится довольно большим, когда мне все время приходится все перекомпилировать.
Есть ли способ использовать преимущества make
(более быстрое время компиляции) и при этом организовать структуру программы в стиле Java (все в теле класса вместо отдельных .h
и .cpp
) что мне гораздо удобнее?
QuadraticFunc
вmain
. Просто используйте автоматическую переменную. - person juanchopanza   schedule 28.12.2015