使用 Makefile 在多个文件 C++ 中构建互连的类
Posted
技术标签:
【中文标题】使用 Makefile 在多个文件 C++ 中构建互连的类【英文标题】:Building interconnected classes in multiple files C++ using Makefile 【发布时间】:2014-10-17 09:35:50 【问题描述】:我不太熟悉从 makefile 构建更复杂的 C++ 程序(我通常使用 IDE 或只做简单的 C 而没有面向对象的编程)。当类在多个文件上相互连接时,我无法弄清楚如何做 makefile。
简单示例:如何将这个单文件程序拆分成单独的文件并使用 Make 构建它:
#include <math.h>
// I want to move this into Vec3d.h
class Vec3d
double x,y,z;
inline void set( const double fx, const double fy, const double fz ) x=fx; y=fy; z=fz;
inline Vec3d& operator+=( const double& f ) x+=f; y+=f; z+=f; return *this;
inline Vec3d operator* ( const double& f ) const Vec3d vo; vo.x=x*f; vo.y=y*f; vo.z=z*f; return vo;
// ... other operators omited for shorness
// I want to move this into Body.h
class Body
double mass;
Vec3d pos,velocity,force; // use Vect3d
void getForce();
void move( double dt ) // use operators defined in Vec3d
getForce();
v += force * -dt;
pos += v * dt;
// I want to move this into Planet.h
class Planet : public Body
void getForce( ) // overrides method from "Body"
double r = sqrt( pos.dot(pos) ) ;
force = pos * ( -dt/(ir*ir*ir) );
// This should be in main.cpp
Vec3d myVector;
Body myBody;
Planet myPlanet;
main()
// ...do something with myVector, myBody and myPlanet
一种选择是将所有内容#include 到 main.cpp。然而,这很糟糕,因为它会一直重新编译所有内容。
我宁愿只重新编译我更改的文件,其余的来自 .o 文件。但要独立编译 Body.h,我必须将 #include Vec3d.h 加入其中。所以 Vec3d.h 会在 main.cpp 中包含两次,这会产生冲突。
我知道在 C 中使用头文件用于此目的,但是当 我想在类主体中定义方法和运算符 时,我不知道如何在 C++ 中使用它(如果可能)(它使程序更具可读性,就像在 Java 中一样)。
【问题讨论】:
除非您使用模板,否则您可以毫无问题地做到这一点。如果你有包含守卫并且那些 TU 真的使用标题的内容,那么多次包含标题并没有错 相关:***.com/questions/21090041/why-include-guards 永远不要在标题中定义任何东西。你有什么问题?创建 foo.cpp 和 foo.h ,在 cpp 中包含 .h ,在 cpp 中定义它们,在 main 中包含 .h ,使用它。如果您希望它在其他类中使用一次编译指示或用户标头指令 @Etixpp “永远不要在标题中定义任何东西。” 为什么?这是一种非常常见的(绝不是不鼓励的)做法。 它在 C++ 中是一个非常糟糕的做法,只有 Java 开发人员甚至会考虑这样的事情,看看@巨大的库,它只是一个糟糕的编码,就像使用命名空间 std 和全局变量一样。很多人这样做,但它仍然很糟糕 【参考方案1】:好的,所以我想对菜鸟问题感到抱歉。唯一的问题是,对于 Vec3d,内联方法必须直接在 .h 文件中声明。整个解决方案是:
生成文件
all: program
program: main.o Planet.o Body.o
g++ main.o Planet.o Body.o -o program
main: main.cpp
g++ -c main.cpp
Body.o: Body.cpp
g++ -c Body.cpp
Planet.o: Planet.cpp
g++ -c Planet.cpp
clean:
rm -rf *o hello
main.cpp:
#include "Vec3d.h"
#include "Body.h"
#include "Planet.h"
Vec3d myVector;
Body myBody;
Planet myPlanet;
int main()
myVector.set(1);
myBody.pos.set(1);
myBody.move(0.1);
myPlanet.getForce();
myPlanet.move(0.1);
行星.h:
class Planet : public Body
public:
void getForce( );
//void move( );
;
行星.cpp:
#include <math.h>
#include "Vec3d.h"
#include "Body.h"
#include "Planet.h"
void Planet::getForce()
double r = sqrt( pos.mag2() );
force = pos * ( mass/(r*r*r) );
正文.h:
class Body
public:
// parameters
double mass;
// state variables
Vec3d pos,vel;
// temporary variables
Vec3d force;
// methods
void getForce();
void move( double dt );
;
正文.cpp:
#include "Vec3d.h"
#include "Body.h"
void Body::getForce() force.set(0); ;
void Body::move( double dt )
vel += force * dt;
pos += vel * dt;
Vec3d.h:
// NOTE: "inline" methods must be implemented directly here
class Vec3d
public:
double x,y,z;
inline void set( const double f ) x=f; y=f; z=f; ;
inline void set( const Vec3d& v ) x=v.x; y=v.y; z=v.z; ;
inline void set( const double fx, const double fy, const double fz ) x=fx; y=fy; z=fz; ;
inline Vec3d& operator =( const double f ) x=f; y=f; z=f; return *this; ;
inline Vec3d& operator+=( const double f ) x+=f; y+=f; z+=f; return *this; ;
inline Vec3d& operator*=( const double f ) x*=f; y*=f; z*=f; return *this; ;
inline Vec3d& operator+=( const Vec3d& v ) x+=v.x; y+=v.y; z+=v.z; return *this; ;
inline Vec3d& operator-=( const Vec3d& v ) x-=v.x; y-=v.y; z-=v.z; return *this; ;
inline Vec3d& operator*=( const Vec3d& v ) x*=v.x; y*=v.y; z*=v.z; return *this; ;
inline Vec3d& operator/=( const Vec3d& v ) x/=v.x; y/=v.y; z/=v.z; return *this; ;
inline Vec3d operator+ ( const double f ) const Vec3d vo; vo.x=x+f; vo.y=y+f; vo.z=z+f; return vo; ;
inline Vec3d operator* ( double f ) const Vec3d vo; vo.x=x*f; vo.y=y*f; vo.z=z*f; return vo; ;
inline Vec3d operator+ ( const Vec3d& vi ) const Vec3d vo; vo.x=x+vi.x; vo.y=y+vi.y; vo.z=z+vi.z; return vo; ;
inline Vec3d operator- ( const Vec3d& vi ) const Vec3d vo; vo.x=x-vi.x; vo.y=y-vi.y; vo.z=z-vi.z; return vo; ;
inline Vec3d operator* ( const Vec3d& vi ) const Vec3d vo; vo.x=x*vi.x; vo.y=y*vi.y; vo.z=z*vi.z; return vo; ;
inline Vec3d operator/ ( const Vec3d& vi ) const Vec3d vo; vo.x=x/vi.x; vo.y=y/vi.y; vo.z=z/vi.z; return vo; ;
inline void fma( const double f, const Vec3d& b ) x+=f*b.x; y+=f*b.y; z+=f*b.z; ;
inline void fma( const Vec3d& a, const Vec3d& b ) x+=a.x*b.x; y+=a.y*b.y; z+=a.z*b.z; ;
inline void fms( const Vec3d& a, const Vec3d& b ) x-=a.x*b.x; y-=a.y*b.y; z-=a.z*b.z; ;
inline void fda( const Vec3d& a, const Vec3d& b ) x+=a.x/b.x; y+=a.y/b.y; z+=a.z/b.z; ;
inline void fds( const Vec3d& a, const Vec3d& b ) x-=a.x/b.x; y-=a.y/b.y; z-=a.z/b.z; ;
inline Vec3d fma_func( const double f, const Vec3d& b ) Vec3d vo; vo.x=x+f*b.x; vo.y=y+f*b.y; vo.x=z+f*b.z; return vo; ;
inline Vec3d fma_func( const Vec3d& a, const Vec3d& b ) Vec3d vo; vo.x=x+a.x*b.x; vo.y=y+a.y*b.y; vo.z=z+a.z*b.z; return vo; ;
inline Vec3d fms_func( const Vec3d& a, const Vec3d& b ) Vec3d vo; vo.x=x-a.x*b.x; vo.y=y-a.y*b.y; vo.z=z-a.z*b.z; return vo; ;
inline Vec3d fda_func( const Vec3d& a, const Vec3d& b ) Vec3d vo; vo.x=x+a.x/b.x; vo.y=y+a.y/b.y; vo.z=z+a.z/b.z; return vo; ;
inline Vec3d fds_func( const Vec3d& a, const Vec3d& b ) Vec3d vo; vo.x=x-a.x/b.x; vo.y=y-a.y/b.y; vo.z=z-a.z/b.z; return vo; ;
inline double dot ( const Vec3d& a ) return x*a.x + y*a.y + z*a.z; ;
inline double mag2( ) return x*x+y*y+z*z; ;
inline void cross ( const Vec3d& a ) double _x=y*a.z-z*a.y; double _y=z*a.x-x*a.z; z=x*a.y-y*a.x; x=_x; y=_y; ;
inline Vec3d cross_func( const Vec3d& a ) Vec3d vo; vo.x=y*a.z-z*a.y; vo.y=z*a.x-x*a.z; vo.z=x*a.y-y*a.x; return vo; ;
;
【讨论】:
以上是关于使用 Makefile 在多个文件 C++ 中构建互连的类的主要内容,如果未能解决你的问题,请参考以下文章
在 makefile 中为 Visual Studio C++ 构建定义宏
使用 Makefile.am/Makefile.in 在 Ubuntu Linux 中构建 c++ 项目